xref: /aosp_15_r20/frameworks/native/services/inputflinger/tests/InputDispatcher_test.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
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 
17 #include "../dispatcher/InputDispatcher.h"
18 #include "FakeApplicationHandle.h"
19 #include "FakeInputDispatcherPolicy.h"
20 #include "FakeInputTracingBackend.h"
21 #include "FakeWindows.h"
22 #include "TestEventMatchers.h"
23 
24 #include <NotifyArgsBuilders.h>
25 #include <android-base/logging.h>
26 #include <android-base/properties.h>
27 #include <android-base/silent_death_test.h>
28 #include <android-base/stringprintf.h>
29 #include <android-base/thread_annotations.h>
30 #include <binder/Binder.h>
31 #include <com_android_input_flags.h>
32 #include <fcntl.h>
33 #include <flag_macros.h>
34 #include <gmock/gmock.h>
35 #include <gtest/gtest.h>
36 #include <input/BlockingQueue.h>
37 #include <input/Input.h>
38 #include <input/InputConsumer.h>
39 #include <input/PrintTools.h>
40 #include <linux/input.h>
41 #include <sys/epoll.h>
42 
43 #include <cinttypes>
44 #include <compare>
45 #include <thread>
46 #include <unordered_set>
47 #include <vector>
48 
49 using android::base::StringPrintf;
50 using android::gui::FocusRequest;
51 using android::gui::TouchOcclusionMode;
52 using android::gui::WindowInfo;
53 using android::gui::WindowInfoHandle;
54 using android::os::InputEventInjectionResult;
55 using android::os::InputEventInjectionSync;
56 
57 namespace android::inputdispatcher {
58 
59 using namespace ftl::flag_operators;
60 using testing::AllOf;
61 using testing::Not;
62 using testing::Pointee;
63 using testing::UnorderedElementsAre;
64 
65 namespace {
66 
67 // An arbitrary time value.
68 static constexpr nsecs_t ARBITRARY_TIME = 1234;
69 
70 // An arbitrary device id.
71 static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
72 static constexpr int32_t SECOND_DEVICE_ID = 2;
73 
74 // An arbitrary display id.
75 constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
76 constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{1};
77 
78 // Ensure common actions are interchangeable between keys and motions for convenience.
79 static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
80 static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
81 static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
82 static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
83 static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
84 static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
85 static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
86 static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
87 static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
88 static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
89 static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
90 /**
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  */
98 static constexpr int32_t POINTER_0_DOWN =
99         AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
100 static constexpr int32_t POINTER_1_DOWN =
101         AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
102 static constexpr int32_t POINTER_2_DOWN =
103         AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
104 static constexpr int32_t POINTER_3_DOWN =
105         AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
106 static constexpr int32_t POINTER_0_UP =
107         AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
108 static constexpr int32_t POINTER_1_UP =
109         AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
110 static constexpr int32_t POINTER_2_UP =
111         AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
112 
113 // The default pid and uid for the windows created on the secondary display by the test.
114 static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
115 static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
116 
117 // An arbitrary pid of the gesture monitor window
118 static constexpr gui::Pid MONITOR_PID{2001};
119 
120 static constexpr int EXPECTED_WALLPAPER_FLAGS =
121         AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
122 
123 using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
124 
125 /**
126  * Return a DOWN key event with KEYCODE_A.
127  */
getTestKeyEvent()128 static KeyEvent getTestKeyEvent() {
129     KeyEvent event;
130 
131     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);
134     return event;
135 }
136 
137 /**
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  */
143 class ScopedFlagOverride {
144 public:
ScopedFlagOverride(std::function<bool ()> read,std::function<void (bool)> write,bool value)145     ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
146           : mInitialValue(read()), mWriteValue(write) {
147         mWriteValue(value);
148     }
~ScopedFlagOverride()149     ~ScopedFlagOverride() { mWriteValue(mInitialValue); }
150 
151 private:
152     const bool mInitialValue;
153     std::function<void(bool)> mWriteValue;
154 };
155 
156 typedef bool (*readFlagValueFunction)();
157 typedef 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 
171 } // namespace
172 
173 // --- InputDispatcherTest ---
174 
175 class InputDispatcherTest : public testing::Test {
176 protected:
177     std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
178     std::unique_ptr<InputDispatcher> mDispatcher;
179     std::shared_ptr<VerifyingTrace> mVerifyingTrace;
180 
SetUp()181     void SetUp() override {
182         mVerifyingTrace = std::make_shared<VerifyingTrace>();
183         FakeWindowHandle::sOnEventReceivedCallback = [this](const auto& _1, const auto& _2) {
184             handleEventReceivedByWindow(_1, _2);
185         };
186 
187         mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
188         mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
189                                                         std::make_unique<FakeInputTracingBackend>(
190                                                                 mVerifyingTrace));
191 
192         mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
193         // Start InputDispatcher thread
194         ASSERT_EQ(OK, mDispatcher->start());
195     }
196 
TearDown()197     void TearDown() override {
198         ASSERT_NO_FATAL_FAILURE(mVerifyingTrace->verifyExpectedEventsTraced());
199         FakeWindowHandle::sOnEventReceivedCallback = nullptr;
200 
201         ASSERT_EQ(OK, mDispatcher->stop());
202         mFakePolicy.reset();
203         mDispatcher.reset();
204     }
205 
handleEventReceivedByWindow(const std::unique_ptr<InputEvent> & event,const gui::WindowInfo & info)206     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 
227     /**
228      * Used for debugging when writing the test
229      */
dumpDispatcherState()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     }
240 
setFocusedWindow(const sp<WindowInfoHandle> & window)241     void setFocusedWindow(const sp<WindowInfoHandle>& window) {
242         FocusRequest request;
243         request.token = window->getToken();
244         request.windowName = window->getName();
245         request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
246         request.displayId = window->getInfo()->displayId.val();
247         mDispatcher->setFocusedWindow(request);
248     }
249 };
250 
TEST_F(InputDispatcherTest,InjectInputEvent_ValidatesKeyEvents)251 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
252     KeyEvent event;
253 
254     // Rejects undefined key actions.
255     event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
256                      ui::LogicalDisplayId::INVALID, INVALID_HMAC,
257                      /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
258                      ARBITRARY_TIME);
259     ASSERT_EQ(InputEventInjectionResult::FAILED,
260               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
261                                             0ms, 0))
262             << "Should reject key events with undefined action.";
263 
264     // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
265     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);
268     ASSERT_EQ(InputEventInjectionResult::FAILED,
269               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
270                                             0ms, 0))
271             << "Should reject key events with ACTION_MULTIPLE.";
272 }
273 
TEST_F(InputDispatcherTest,InjectInputEvent_ValidatesMotionEvents)274 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
275     MotionEvent event;
276     PointerProperties pointerProperties[MAX_POINTERS + 1];
277     PointerCoords pointerCoords[MAX_POINTERS + 1];
278     for (size_t i = 0; i <= MAX_POINTERS; i++) {
279         pointerProperties[i].clear();
280         pointerProperties[i].id = i;
281         pointerCoords[i].clear();
282     }
283 
284     // 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 
290     ui::Transform identityTransform;
291     // Rejects undefined motion actions.
292     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
293                      /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
294                      identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
295                      AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
296                      ARBITRARY_TIME,
297                      /*pointerCount=*/1, pointerProperties, pointerCoords);
298     ASSERT_EQ(InputEventInjectionResult::FAILED,
299               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
300                                             0ms, 0))
301             << "Should reject motion events with undefined action.";
302 
303     // Rejects pointer down with invalid index.
304     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
305                      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,
309                      /*pointerCount=*/1, pointerProperties, pointerCoords);
310     ASSERT_EQ(InputEventInjectionResult::FAILED,
311               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
312                                             0ms, 0))
313             << "Should reject motion events with pointer down index too large.";
314 
315     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
316                      AMOTION_EVENT_ACTION_POINTER_DOWN |
317                              (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
318                      0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
319                      AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
320                      identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
321                      /*pointerCount=*/1, pointerProperties, pointerCoords);
322     ASSERT_EQ(InputEventInjectionResult::FAILED,
323               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
324                                             0ms, 0))
325             << "Should reject motion events with pointer down index too small.";
326 
327     // Rejects pointer up with invalid index.
328     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
329                      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,
333                      /*pointerCount=*/1, pointerProperties, pointerCoords);
334     ASSERT_EQ(InputEventInjectionResult::FAILED,
335               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
336                                             0ms, 0))
337             << "Should reject motion events with pointer up index too large.";
338 
339     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
340                      AMOTION_EVENT_ACTION_POINTER_UP |
341                              (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
342                      0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
343                      AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
344                      identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
345                      /*pointerCount=*/1, pointerProperties, pointerCoords);
346     ASSERT_EQ(InputEventInjectionResult::FAILED,
347               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
348                                             0ms, 0))
349             << "Should reject motion events with pointer up index too small.";
350 
351     // Rejects motion events with invalid number of pointers.
352     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
353                      AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
354                      identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
355                      AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
356                      ARBITRARY_TIME,
357                      /*pointerCount=*/0, pointerProperties, pointerCoords);
358     ASSERT_EQ(InputEventInjectionResult::FAILED,
359               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
360                                             0ms, 0))
361             << "Should reject motion events with 0 pointers.";
362 
363     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
364                      AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
365                      identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
366                      AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
367                      ARBITRARY_TIME,
368                      /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
369     ASSERT_EQ(InputEventInjectionResult::FAILED,
370               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
371                                             0ms, 0))
372             << "Should reject motion events with more than MAX_POINTERS pointers.";
373 
374     // Rejects motion events with invalid pointer ids.
375     pointerProperties[0].id = -1;
376     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
377                      AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
378                      identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
379                      AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
380                      ARBITRARY_TIME,
381                      /*pointerCount=*/1, pointerProperties, pointerCoords);
382     ASSERT_EQ(InputEventInjectionResult::FAILED,
383               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
384                                             0ms, 0))
385             << "Should reject motion events with pointer ids less than 0.";
386 
387     pointerProperties[0].id = MAX_POINTER_ID + 1;
388     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
389                      AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
390                      identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
391                      AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
392                      ARBITRARY_TIME,
393                      /*pointerCount=*/1, pointerProperties, pointerCoords);
394     ASSERT_EQ(InputEventInjectionResult::FAILED,
395               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
396                                             0ms, 0))
397             << "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;
402     event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
403                      AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
404                      identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
405                      AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
406                      ARBITRARY_TIME,
407                      /*pointerCount=*/2, pointerProperties, pointerCoords);
408     ASSERT_EQ(InputEventInjectionResult::FAILED,
409               mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
410                                             0ms, 0))
411             << "Should reject motion events with duplicate pointer ids.";
412 }
413 
TEST_F(InputDispatcherTest,NotifySwitch_CallsPolicy)414 TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
415     NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
416                           /*switchValues=*/1,
417                           /*switchMask=*/2);
418     mDispatcher->notifySwitch(args);
419 
420     // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
421     args.policyFlags |= POLICY_FLAG_TRUSTED;
422     mFakePolicy->assertNotifySwitchWasCalled(args);
423 }
424 
425 namespace {
426 
427 static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
428 
429 class FakeMonitorReceiver {
430 public:
FakeMonitorReceiver(InputDispatcher & dispatcher,const std::string name,ui::LogicalDisplayId displayId)431     FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
432                         ui::LogicalDisplayId displayId)
433           : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
434 
getToken()435     sp<IBinder> getToken() { return mInputReceiver.getToken(); }
436 
consumeKeyDown(ui::LogicalDisplayId expectedDisplayId,int32_t expectedFlags=0)437     void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
438         mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
439                                     expectedFlags);
440     }
441 
receiveEvent()442     std::optional<int32_t> receiveEvent() {
443         const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
444         return sequenceNum;
445     }
446 
finishEvent(uint32_t consumeSeq)447     void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
448 
consumeMotionDown(ui::LogicalDisplayId expectedDisplayId,int32_t expectedFlags=0)449     void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
450         mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
451                                     expectedDisplayId, expectedFlags);
452     }
453 
consumeMotionMove(ui::LogicalDisplayId expectedDisplayId,int32_t expectedFlags=0)454     void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
455         mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
456                                     expectedDisplayId, expectedFlags);
457     }
458 
consumeMotionUp(ui::LogicalDisplayId expectedDisplayId,int32_t expectedFlags=0)459     void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
460         mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
461                                     expectedDisplayId, expectedFlags);
462     }
463 
consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId,int32_t expectedFlags=0)464     void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
465         mInputReceiver.consumeMotionEvent(
466                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
467                       WithDisplayId(expectedDisplayId),
468                       WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
469     }
470 
consumeMotionPointerDown(int32_t pointerIdx)471     void consumeMotionPointerDown(int32_t pointerIdx) {
472         int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
473                 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
474         mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
475                                     /*expectedFlags=*/0);
476     }
477 
consumeMotionEvent(const::testing::Matcher<MotionEvent> & matcher)478     void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
479         mInputReceiver.consumeMotionEvent(matcher);
480     }
481 
consumeMotion()482     std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
483 
assertNoEvents()484     void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
485 
486 private:
487     FakeInputReceiver mInputReceiver;
488 };
489 
injectKey(InputDispatcher & dispatcher,int32_t action,int32_t repeatCount,ui::LogicalDisplayId displayId=ui::LogicalDisplayId::INVALID,InputEventInjectionSync syncMode=InputEventInjectionSync::WAIT_FOR_RESULT,std::chrono::milliseconds injectionTimeout=INJECT_EVENT_TIMEOUT,bool allowKeyRepeat=true,std::optional<gui::Uid> targetUid={},uint32_t policyFlags=DEFAULT_POLICY_FLAGS)490 static InputEventInjectionResult injectKey(
491         InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
492         ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
493         InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
494         std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
495         bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
496         uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
497     KeyEvent event;
498     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
499 
500     // Define a valid key down event.
501     event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
502                      INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
503                      currentTime, currentTime);
504 
505     if (!allowKeyRepeat) {
506         policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
507     }
508     // Inject event until dispatch out.
509     return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
510 }
511 
assertInjectedKeyTimesOut(InputDispatcher & dispatcher)512 static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
513     InputEventInjectionResult result =
514             injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
515                       ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
516                       CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
517     if (result != InputEventInjectionResult::TIMED_OUT) {
518         FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
519     }
520 }
521 
injectKeyDown(InputDispatcher & dispatcher,ui::LogicalDisplayId displayId=ui::LogicalDisplayId::INVALID)522 static InputEventInjectionResult injectKeyDown(
523         InputDispatcher& dispatcher,
524         ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
525     return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
526 }
527 
528 // Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
529 // sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
530 // has to be woken up to process the repeating key.
injectKeyDownNoRepeat(InputDispatcher & dispatcher,ui::LogicalDisplayId displayId=ui::LogicalDisplayId::INVALID)531 static InputEventInjectionResult injectKeyDownNoRepeat(
532         InputDispatcher& dispatcher,
533         ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
534     return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
535                      InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
536                      /*allowKeyRepeat=*/false);
537 }
538 
injectKeyUp(InputDispatcher & dispatcher,ui::LogicalDisplayId displayId=ui::LogicalDisplayId::INVALID)539 static InputEventInjectionResult injectKeyUp(
540         InputDispatcher& dispatcher,
541         ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
542     return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
543 }
544 
injectMotionEvent(InputDispatcher & dispatcher,const MotionEvent & event,std::chrono::milliseconds injectionTimeout=INJECT_EVENT_TIMEOUT,InputEventInjectionSync injectionMode=InputEventInjectionSync::WAIT_FOR_RESULT,std::optional<gui::Uid> targetUid={},uint32_t policyFlags=DEFAULT_POLICY_FLAGS)545 static InputEventInjectionResult injectMotionEvent(
546         InputDispatcher& dispatcher, const MotionEvent& event,
547         std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
548         InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
549         std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
550     return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
551                                        policyFlags);
552 }
553 
injectMotionEvent(InputDispatcher & dispatcher,int32_t action,int32_t source,ui::LogicalDisplayId displayId,const PointF & position={100, 200},const PointF & cursorPosition={AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION},std::chrono::milliseconds injectionTimeout=INJECT_EVENT_TIMEOUT,InputEventInjectionSync injectionMode=InputEventInjectionSync::WAIT_FOR_RESULT,nsecs_t eventTime=systemTime (SYSTEM_TIME_MONOTONIC),std::optional<gui::Uid> targetUid={},uint32_t policyFlags=DEFAULT_POLICY_FLAGS)554 static InputEventInjectionResult injectMotionEvent(
555         InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
556         const PointF& position = {100, 200},
557         const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
558                                         AMOTION_EVENT_INVALID_CURSOR_POSITION},
559         std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
560         InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
561         nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
562         std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
563     MotionEventBuilder motionBuilder =
564             MotionEventBuilder(action, source)
565                     .displayId(displayId)
566                     .eventTime(eventTime)
567                     .rawXCursorPosition(cursorPosition.x)
568                     .rawYCursorPosition(cursorPosition.y)
569                     .pointer(
570                             PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
571     if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
572         motionBuilder.downTime(eventTime);
573     }
574 
575     // Inject event until dispatch out.
576     return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
577                              targetUid, policyFlags);
578 }
579 
injectMotionDown(InputDispatcher & dispatcher,int32_t source,ui::LogicalDisplayId displayId,const PointF & location={100, 200})580 static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
581                                                   ui::LogicalDisplayId displayId,
582                                                   const PointF& location = {100, 200}) {
583     return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
584 }
585 
injectMotionUp(InputDispatcher & dispatcher,int32_t source,ui::LogicalDisplayId displayId,const PointF & location={100, 200})586 static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
587                                                 ui::LogicalDisplayId displayId,
588                                                 const PointF& location = {100, 200}) {
589     return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
590 }
591 
generateKeyArgs(int32_t action,ui::LogicalDisplayId displayId=ui::LogicalDisplayId::INVALID)592 static NotifyKeyArgs generateKeyArgs(
593         int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
594     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
595     // Define a valid key event.
596     NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
597                        AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
598                        /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
599 
600     return args;
601 }
602 
generateMotionArgs(int32_t action,int32_t source,ui::LogicalDisplayId displayId,const std::vector<PointF> & points)603 [[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
604                                                          ui::LogicalDisplayId displayId,
605                                                          const std::vector<PointF>& points) {
606     size_t pointerCount = points.size();
607     if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
608         EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
609     }
610 
611     PointerProperties pointerProperties[pointerCount];
612     PointerCoords pointerCoords[pointerCount];
613 
614     for (size_t i = 0; i < pointerCount; i++) {
615         pointerProperties[i].clear();
616         pointerProperties[i].id = i;
617         pointerProperties[i].toolType = ToolType::FINGER;
618 
619         pointerCoords[i].clear();
620         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
621         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
622     }
623 
624     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
625     // Define a valid motion event.
626     NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
627                           displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
628                           /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
629                           AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
630                           pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
631                           AMOTION_EVENT_INVALID_CURSOR_POSITION,
632                           AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
633 
634     return args;
635 }
636 
generateTouchArgs(int32_t action,const std::vector<PointF> & points)637 static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
638     return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
639 }
640 
generateMotionArgs(int32_t action,int32_t source,ui::LogicalDisplayId displayId)641 static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
642                                            ui::LogicalDisplayId displayId) {
643     return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
644 }
645 
generatePointerCaptureChangedArgs(const PointerCaptureRequest & request)646 static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
647         const PointerCaptureRequest& request) {
648     return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
649                                            request);
650 }
651 
652 } // namespace
653 
654 /**
655  * When a window unexpectedly disposes of its input channel, policy should be notified about the
656  * broken channel.
657  */
TEST_F(InputDispatcherTest,WhenInputChannelBreaks_PolicyIsNotified)658 TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
659     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
660     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
661                                                              "Window that breaks its input channel",
662                                                              ui::LogicalDisplayId::DEFAULT);
663 
664     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
665 
666     // Window closes its channel, but the window remains.
667     window->destroyReceiver();
668     mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
669 }
670 
TEST_F(InputDispatcherTest,SetInputWindow_SingleWindowTouch)671 TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
672     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
673     sp<FakeWindowHandle> window =
674             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
675                                        ui::LogicalDisplayId::DEFAULT);
676 
677     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
678     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
679               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
680                                ui::LogicalDisplayId::DEFAULT))
681             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
682 
683     // Window should receive motion event.
684     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
685 }
686 
687 using InputDispatcherDeathTest = InputDispatcherTest;
688 
689 /**
690  * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
691  * should crash.
692  */
TEST_F(InputDispatcherDeathTest,DuplicateWindowInfosAbortDispatcher)693 TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
694     testing::GTEST_FLAG(death_test_style) = "threadsafe";
695     ScopedSilentDeath _silentDeath;
696 
697     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
698     sp<FakeWindowHandle> window =
699             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
700                                        ui::LogicalDisplayId::DEFAULT);
701     ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
702                          {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
703                  "Incorrect WindowInfosUpdate provided");
704 }
705 
TEST_F(InputDispatcherTest,WhenDisplayNotSpecified_InjectMotionToDefaultDisplay)706 TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
707     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
708     sp<FakeWindowHandle> window =
709             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
710                                        ui::LogicalDisplayId::DEFAULT);
711 
712     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
713     // Inject a MotionEvent to an unknown display.
714     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
715               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
716                                ui::LogicalDisplayId::INVALID))
717             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
718 
719     // Window should receive motion event.
720     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
721 }
722 
723 /**
724  * Calling onWindowInfosChanged once should not cause any issues.
725  * This test serves as a sanity check for the next test, where onWindowInfosChanged is
726  * called twice.
727  */
TEST_F(InputDispatcherTest,SetInputWindowOnceWithSingleTouchWindow)728 TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
729     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
730     sp<FakeWindowHandle> window =
731             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
732                                        ui::LogicalDisplayId::DEFAULT);
733     window->setFrame(Rect(0, 0, 100, 100));
734 
735     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
736     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
737               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
738                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
739             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
740 
741     // Window should receive motion event.
742     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
743 }
744 
745 /**
746  * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
747  */
TEST_F(InputDispatcherTest,SetInputWindowTwice_SingleWindowTouch)748 TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
749     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
750     sp<FakeWindowHandle> window =
751             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
752                                        ui::LogicalDisplayId::DEFAULT);
753     window->setFrame(Rect(0, 0, 100, 100));
754 
755     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
756     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
757     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
758               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
759                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
760             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
761 
762     // Window should receive motion event.
763     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
764 }
765 
766 // The foreground window should receive the first touch down event.
TEST_F(InputDispatcherTest,SetInputWindow_MultiWindowsTouch)767 TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
768     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
769     sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
770                                                                 ui::LogicalDisplayId::DEFAULT);
771     sp<FakeWindowHandle> windowSecond =
772             sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
773                                        ui::LogicalDisplayId::DEFAULT);
774 
775     mDispatcher->onWindowInfosChanged(
776             {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
777     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
778               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
779                                ui::LogicalDisplayId::DEFAULT))
780             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
781 
782     // Top window should receive the touch down event. Second window should not receive anything.
783     windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
784     windowSecond->assertNoEvents();
785 }
786 
787 /**
788  * Two windows: A top window, and a wallpaper behind the window.
789  * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
790  * gets ACTION_CANCEL.
791  * 1. foregroundWindow <-- dup touch to wallpaper
792  * 2. wallpaperWindow <-- is wallpaper
793  */
TEST_F(InputDispatcherTest,WhenForegroundWindowDisappears_WallpaperTouchIsCanceled)794 TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
795     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
796     sp<FakeWindowHandle> foregroundWindow =
797             sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
798                                        ui::LogicalDisplayId::DEFAULT);
799     foregroundWindow->setDupTouchToWallpaper(true);
800     sp<FakeWindowHandle> wallpaperWindow =
801             sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
802                                        ui::LogicalDisplayId::DEFAULT);
803     wallpaperWindow->setIsWallpaper(true);
804 
805     mDispatcher->onWindowInfosChanged(
806             {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
807     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
808               injectMotionEvent(*mDispatcher,
809                                 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
810                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
811                                         .build()))
812             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
813 
814     // Both foreground window and its wallpaper should receive the touch down
815     foregroundWindow->consumeMotionDown();
816     wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
817 
818     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
819               injectMotionEvent(*mDispatcher,
820                                 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
821                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
822                                         .build()))
823             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
824 
825     foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
826     wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
827 
828     // Now the foreground window goes away, but the wallpaper stays
829     mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
830     foregroundWindow->consumeMotionCancel();
831     // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
832     wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
833 }
834 
835 /**
836  * Two fingers down on the window, and lift off the first finger.
837  * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
838  * contains a single pointer.
839  */
TEST_F(InputDispatcherTest,CancelAfterPointer0Up)840 TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
841     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
842     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
843                                                              ui::LogicalDisplayId::DEFAULT);
844 
845     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
846     // First touch pointer down on right window
847     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
848                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
849                                       .build());
850     // Second touch pointer down
851     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
852                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
853                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
854                                       .build());
855     // First touch pointer lifts. The second one remains down
856     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
857                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
858                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
859                                       .build());
860     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
861     window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
862     window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
863 
864     // Remove the window. The gesture should be canceled
865     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
866     const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
867     window->consumeMotionEvent(
868             AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
869 }
870 
871 /**
872  * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
873  * with the following differences:
874  * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
875  * clean up the connection.
876  * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
877  * Ensure that there's no crash in the dispatcher.
878  */
TEST_F(InputDispatcherTest,WhenWallpaperDisappears_NoCrash)879 TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
880     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
881     sp<FakeWindowHandle> foregroundWindow =
882             sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
883                                        ui::LogicalDisplayId::DEFAULT);
884     foregroundWindow->setDupTouchToWallpaper(true);
885     sp<FakeWindowHandle> wallpaperWindow =
886             sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
887                                        ui::LogicalDisplayId::DEFAULT);
888     wallpaperWindow->setIsWallpaper(true);
889 
890     mDispatcher->onWindowInfosChanged(
891             {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
892     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
893               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
894                                ui::LogicalDisplayId::DEFAULT, {100, 200}))
895             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
896 
897     // Both foreground window and its wallpaper should receive the touch down
898     foregroundWindow->consumeMotionDown();
899     wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
900 
901     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
902               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
903                                 ui::LogicalDisplayId::DEFAULT, {110, 200}))
904             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
905 
906     foregroundWindow->consumeMotionMove();
907     wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
908 
909     // Wallpaper closes its channel, but the window remains.
910     wallpaperWindow->destroyReceiver();
911     mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
912 
913     // Now the foreground window goes away, but the wallpaper stays, even though its channel
914     // is no longer valid.
915     mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
916     foregroundWindow->consumeMotionCancel();
917 }
918 
919 /**
920  * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
921  * down event to the left window. Device B sends a down event to the right window. Next, the right
922  * window disappears. Both the right window and its wallpaper window should receive cancel event.
923  * The left window and its wallpaper window should not receive any events.
924  */
TEST_F(InputDispatcherTest,MultiDeviceDisappearingWindowWithWallpaperWindows)925 TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
926     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
927     sp<FakeWindowHandle> leftForegroundWindow =
928             sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
929                                        ui::LogicalDisplayId::DEFAULT);
930     leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
931     leftForegroundWindow->setDupTouchToWallpaper(true);
932     sp<FakeWindowHandle> leftWallpaperWindow =
933             sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
934                                        ui::LogicalDisplayId::DEFAULT);
935     leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
936     leftWallpaperWindow->setIsWallpaper(true);
937 
938     sp<FakeWindowHandle> rightForegroundWindow =
939             sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
940                                        ui::LogicalDisplayId::DEFAULT);
941     rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
942     rightForegroundWindow->setDupTouchToWallpaper(true);
943     sp<FakeWindowHandle> rightWallpaperWindow =
944             sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
945                                        ui::LogicalDisplayId::DEFAULT);
946     rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
947     rightWallpaperWindow->setIsWallpaper(true);
948 
949     mDispatcher->onWindowInfosChanged(
950             {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
951               *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
952              {},
953              0,
954              0});
955 
956     const DeviceId deviceA = 9;
957     const DeviceId deviceB = 3;
958     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
959                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
960                                       .deviceId(deviceA)
961                                       .build());
962     leftForegroundWindow->consumeMotionEvent(
963             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
964     leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
965                                                   WithDeviceId(deviceA),
966                                                   WithFlags(EXPECTED_WALLPAPER_FLAGS)));
967 
968     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
969                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
970                                       .deviceId(deviceB)
971                                       .build());
972     rightForegroundWindow->consumeMotionEvent(
973             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
974     rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
975                                                    WithDeviceId(deviceB),
976                                                    WithFlags(EXPECTED_WALLPAPER_FLAGS)));
977 
978     // Now right foreground window disappears, but right wallpaper window remains.
979     mDispatcher->onWindowInfosChanged(
980             {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
981               *rightWallpaperWindow->getInfo()},
982              {},
983              0,
984              0});
985 
986     // Left foreground window and left wallpaper window still exist, and should not receive any
987     // events.
988     leftForegroundWindow->assertNoEvents();
989     leftWallpaperWindow->assertNoEvents();
990     // Since right foreground window disappeared, right wallpaper window and right foreground window
991     // should receive cancel events.
992     rightForegroundWindow->consumeMotionEvent(
993             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
994     rightWallpaperWindow->consumeMotionEvent(
995             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
996                   WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
997 }
998 
999 /**
1000  * Three windows arranged horizontally and without any overlap. Every window has a
1001  * wallpaper window underneath. The middle window also has SLIPPERY flag.
1002  * Device A sends a down event to the left window. Device B sends a down event to the middle window.
1003  * Next, device B sends move event to the right window. Touch for device B should slip from the
1004  * middle window to the right window. Also, the right wallpaper window should receive a down event.
1005  * The middle window and its wallpaper window should receive a cancel event. The left window should
1006  * not receive any events. If device B continues to report events, the right window and its
1007  * wallpaper window should receive remaining events.
1008  */
TEST_F(InputDispatcherTest,MultiDeviceSlipperyTouchWithWallpaperWindow)1009 TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
1010     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1011     sp<FakeWindowHandle> leftForegroundWindow =
1012             sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
1013                                        ui::LogicalDisplayId::DEFAULT);
1014     leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1015     leftForegroundWindow->setDupTouchToWallpaper(true);
1016     sp<FakeWindowHandle> leftWallpaperWindow =
1017             sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
1018                                        ui::LogicalDisplayId::DEFAULT);
1019     leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1020     leftWallpaperWindow->setIsWallpaper(true);
1021 
1022     sp<FakeWindowHandle> middleForegroundWindow =
1023             sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
1024                                        ui::LogicalDisplayId::DEFAULT);
1025     middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1026     middleForegroundWindow->setDupTouchToWallpaper(true);
1027     middleForegroundWindow->setSlippery(true);
1028     sp<FakeWindowHandle> middleWallpaperWindow =
1029             sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
1030                                        ui::LogicalDisplayId::DEFAULT);
1031     middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1032     middleWallpaperWindow->setIsWallpaper(true);
1033 
1034     sp<FakeWindowHandle> rightForegroundWindow =
1035             sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
1036                                        ui::LogicalDisplayId::DEFAULT);
1037     rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1038     rightForegroundWindow->setDupTouchToWallpaper(true);
1039     sp<FakeWindowHandle> rightWallpaperWindow =
1040             sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
1041                                        ui::LogicalDisplayId::DEFAULT);
1042     rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1043     rightWallpaperWindow->setIsWallpaper(true);
1044 
1045     mDispatcher->onWindowInfosChanged(
1046             {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1047               *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1048               *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1049              {},
1050              0,
1051              0});
1052 
1053     const DeviceId deviceA = 9;
1054     const DeviceId deviceB = 3;
1055     // Device A sends a DOWN event to the left window
1056     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1057                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1058                                       .deviceId(deviceA)
1059                                       .build());
1060     leftForegroundWindow->consumeMotionEvent(
1061             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1062     leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1063                                                   WithDeviceId(deviceA),
1064                                                   WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1065     // Device B sends a DOWN event to the middle window
1066     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1067                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1068                                       .deviceId(deviceB)
1069                                       .build());
1070     middleForegroundWindow->consumeMotionEvent(
1071             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1072     middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1073                                                     WithDeviceId(deviceB),
1074                                                     WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1075     // Move the events of device B to the top of the right window.
1076     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1077                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
1078                                       .deviceId(deviceB)
1079                                       .build());
1080     middleForegroundWindow->consumeMotionEvent(
1081             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1082     middleWallpaperWindow->consumeMotionEvent(
1083             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1084                   WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1085     rightForegroundWindow->consumeMotionEvent(
1086             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1087     rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1088                                                    WithDeviceId(deviceB),
1089                                                    WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1090     // Make sure the window on the right can receive the remaining events.
1091     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1092                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1093                                       .deviceId(deviceB)
1094                                       .build());
1095     leftForegroundWindow->assertNoEvents();
1096     leftWallpaperWindow->assertNoEvents();
1097     middleForegroundWindow->assertNoEvents();
1098     middleWallpaperWindow->assertNoEvents();
1099     rightForegroundWindow->consumeMotionEvent(
1100             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
1101     rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1102                                                    WithDeviceId(deviceB),
1103                                                    WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1104 }
1105 
1106 /**
1107  * Similar to the test above, we have three windows, they are arranged horizontally and without any
1108  * overlap, and every window has a wallpaper window. The middle window is a simple window, without
1109  * any special flags. Device A reports a down event that lands in left window. Device B sends a down
1110  * event to the middle window and then touch is transferred from the middle window to the right
1111  * window. The right window and its wallpaper window should receive a down event. The middle window
1112  * and its wallpaper window should receive a cancel event. The left window should not receive any
1113  * events. Subsequent events reported by device B should go to the right window and its wallpaper.
1114  */
TEST_F(InputDispatcherTest,MultiDeviceTouchTransferWithWallpaperWindows)1115 TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
1116     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1117     sp<FakeWindowHandle> leftForegroundWindow =
1118             sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
1119                                        ui::LogicalDisplayId::DEFAULT);
1120     leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1121     leftForegroundWindow->setDupTouchToWallpaper(true);
1122     sp<FakeWindowHandle> leftWallpaperWindow =
1123             sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
1124                                        ui::LogicalDisplayId::DEFAULT);
1125     leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1126     leftWallpaperWindow->setIsWallpaper(true);
1127 
1128     sp<FakeWindowHandle> middleForegroundWindow =
1129             sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
1130                                        ui::LogicalDisplayId::DEFAULT);
1131     middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1132     middleForegroundWindow->setDupTouchToWallpaper(true);
1133     sp<FakeWindowHandle> middleWallpaperWindow =
1134             sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
1135                                        ui::LogicalDisplayId::DEFAULT);
1136     middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1137     middleWallpaperWindow->setIsWallpaper(true);
1138 
1139     sp<FakeWindowHandle> rightForegroundWindow =
1140             sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
1141                                        ui::LogicalDisplayId::DEFAULT);
1142     rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1143     rightForegroundWindow->setDupTouchToWallpaper(true);
1144     sp<FakeWindowHandle> rightWallpaperWindow =
1145             sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
1146                                        ui::LogicalDisplayId::DEFAULT);
1147     rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1148     rightWallpaperWindow->setIsWallpaper(true);
1149 
1150     mDispatcher->onWindowInfosChanged(
1151             {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1152               *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1153               *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1154              {},
1155              0,
1156              0});
1157 
1158     const DeviceId deviceA = 9;
1159     const DeviceId deviceB = 3;
1160     // Device A touch down on the left window
1161     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1162                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1163                                       .deviceId(deviceA)
1164                                       .build());
1165     leftForegroundWindow->consumeMotionEvent(
1166             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1167     leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1168                                                   WithDeviceId(deviceA),
1169                                                   WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1170     // Device B touch down on the middle window
1171     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1172                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1173                                       .deviceId(deviceB)
1174                                       .build());
1175     middleForegroundWindow->consumeMotionEvent(
1176             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1177     middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1178                                                     WithDeviceId(deviceB),
1179                                                     WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1180 
1181     // Transfer touch from the middle window to the right window.
1182     ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
1183                                                   rightForegroundWindow->getToken()));
1184 
1185     middleForegroundWindow->consumeMotionEvent(
1186             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1187     middleWallpaperWindow->consumeMotionEvent(
1188             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1189                   WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1190     rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1191                                                     WithDeviceId(deviceB),
1192                                                     WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1193     rightWallpaperWindow->consumeMotionEvent(
1194             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
1195                   WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1196 
1197     // Make sure the right window can receive the remaining events.
1198     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1199                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1200                                       .deviceId(deviceB)
1201                                       .build());
1202     leftForegroundWindow->assertNoEvents();
1203     leftWallpaperWindow->assertNoEvents();
1204     middleForegroundWindow->assertNoEvents();
1205     middleWallpaperWindow->assertNoEvents();
1206     rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1207                                                     WithDeviceId(deviceB),
1208                                                     WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1209     rightWallpaperWindow->consumeMotionEvent(
1210             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
1211                   WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1212 }
1213 
1214 class ShouldSplitTouchFixture : public InputDispatcherTest,
1215                                 public ::testing::WithParamInterface<bool> {};
1216 INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1217                          ::testing::Values(true, false));
1218 /**
1219  * A single window that receives touch (on top), and a wallpaper window underneath it.
1220  * The top window gets a multitouch gesture.
1221  * Ensure that wallpaper gets the same gesture.
1222  */
TEST_P(ShouldSplitTouchFixture,WallpaperWindowReceivesMultiTouch)1223 TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
1224     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1225     sp<FakeWindowHandle> foregroundWindow =
1226             sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
1227                                        ui::LogicalDisplayId::DEFAULT);
1228     foregroundWindow->setDupTouchToWallpaper(true);
1229     foregroundWindow->setPreventSplitting(GetParam());
1230 
1231     sp<FakeWindowHandle> wallpaperWindow =
1232             sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1233                                        ui::LogicalDisplayId::DEFAULT);
1234     wallpaperWindow->setIsWallpaper(true);
1235 
1236     mDispatcher->onWindowInfosChanged(
1237             {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
1238 
1239     // Touch down on top window
1240     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1241               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1242                                ui::LogicalDisplayId::DEFAULT, {100, 100}))
1243             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1244 
1245     // Both top window and its wallpaper should receive the touch down
1246     foregroundWindow->consumeMotionDown();
1247     wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
1248 
1249     // Second finger down on the top window
1250     const MotionEvent secondFingerDownEvent =
1251             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1252                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1253                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1254                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
1255                     .build();
1256     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1257               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1258                                 InputEventInjectionSync::WAIT_FOR_RESULT))
1259             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1260     foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1261     wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
1262                                               EXPECTED_WALLPAPER_FLAGS);
1263 
1264     const MotionEvent secondFingerUpEvent =
1265             MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1266                     .displayId(ui::LogicalDisplayId::DEFAULT)
1267                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1268                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1269                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
1270                     .build();
1271     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1272               injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1273                                 InputEventInjectionSync::WAIT_FOR_RESULT))
1274             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1275     foregroundWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1276                                              WithDisplayId(ui::LogicalDisplayId::DEFAULT));
1277     wallpaperWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1278                                             AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
1279                                                   WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1280 
1281     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1282               injectMotionEvent(*mDispatcher,
1283                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1284                                                    AINPUT_SOURCE_TOUCHSCREEN)
1285                                         .displayId(ui::LogicalDisplayId::DEFAULT)
1286                                         .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1287                                         .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
1288                                                          .x(100)
1289                                                          .y(100))
1290                                         .build(),
1291                                 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
1292             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1293     foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1294     wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
1295 }
1296 
1297 /**
1298  * Two windows: a window on the left and window on the right.
1299  * A third window, wallpaper, is behind both windows, and spans both top windows.
1300  * The first touch down goes to the left window. A second pointer touches down on the right window.
1301  * The touch is split, so both left and right windows should receive ACTION_DOWN.
1302  * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1303  * ACTION_POINTER_DOWN(1).
1304  */
TEST_F(InputDispatcherTest,TwoWindows_SplitWallpaperTouch)1305 TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1306     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1307     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1308                                                                  ui::LogicalDisplayId::DEFAULT);
1309     leftWindow->setFrame(Rect(0, 0, 200, 200));
1310     leftWindow->setDupTouchToWallpaper(true);
1311 
1312     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1313                                                                   ui::LogicalDisplayId::DEFAULT);
1314     rightWindow->setFrame(Rect(200, 0, 400, 200));
1315     rightWindow->setDupTouchToWallpaper(true);
1316 
1317     sp<FakeWindowHandle> wallpaperWindow =
1318             sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1319                                        ui::LogicalDisplayId::DEFAULT);
1320     wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
1321     wallpaperWindow->setIsWallpaper(true);
1322 
1323     mDispatcher->onWindowInfosChanged(
1324             {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1325              {},
1326              0,
1327              0});
1328 
1329     // Touch down on left window
1330     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1331               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1332                                ui::LogicalDisplayId::DEFAULT, {100, 100}))
1333             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1334 
1335     // Both foreground window and its wallpaper should receive the touch down
1336     leftWindow->consumeMotionDown();
1337     wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
1338 
1339     // Second finger down on the right window
1340     const MotionEvent secondFingerDownEvent =
1341             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1342                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1343                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1344                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
1345                     .build();
1346     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1347               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1348                                 InputEventInjectionSync::WAIT_FOR_RESULT))
1349             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1350 
1351     leftWindow->consumeMotionMove();
1352     // Since the touch is split, right window gets ACTION_DOWN
1353     rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1354     wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
1355                                               EXPECTED_WALLPAPER_FLAGS);
1356 
1357     // Now, leftWindow, which received the first finger, disappears.
1358     mDispatcher->onWindowInfosChanged(
1359             {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
1360     leftWindow->consumeMotionCancel();
1361     // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1362     wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
1363 
1364     // The pointer that's still down on the right window moves, and goes to the right window only.
1365     // As far as the dispatcher's concerned though, both pointers are still present.
1366     const MotionEvent secondFingerMoveEvent =
1367             MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1368                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1369                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1370                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
1371                     .build();
1372     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1373               injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1374                                 InputEventInjectionSync::WAIT_FOR_RESULT));
1375     rightWindow->consumeMotionMove();
1376 
1377     leftWindow->assertNoEvents();
1378     rightWindow->assertNoEvents();
1379     wallpaperWindow->assertNoEvents();
1380 }
1381 
1382 /**
1383  * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1384  * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1385  * The right window should receive ACTION_DOWN.
1386  */
TEST_F(InputDispatcherTest,WallpaperWindowWhenSlippery)1387 TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
1388     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1389     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1390                                                                  ui::LogicalDisplayId::DEFAULT);
1391     leftWindow->setFrame(Rect(0, 0, 200, 200));
1392     leftWindow->setDupTouchToWallpaper(true);
1393     leftWindow->setSlippery(true);
1394 
1395     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1396                                                                   ui::LogicalDisplayId::DEFAULT);
1397     rightWindow->setFrame(Rect(200, 0, 400, 200));
1398 
1399     sp<FakeWindowHandle> wallpaperWindow =
1400             sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1401                                        ui::LogicalDisplayId::DEFAULT);
1402     wallpaperWindow->setIsWallpaper(true);
1403 
1404     mDispatcher->onWindowInfosChanged(
1405             {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1406              {},
1407              0,
1408              0});
1409 
1410     // Touch down on left window
1411     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1412               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1413                                ui::LogicalDisplayId::DEFAULT, {100, 100}))
1414             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1415 
1416     // Both foreground window and its wallpaper should receive the touch down
1417     leftWindow->consumeMotionDown();
1418     wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
1419 
1420     // Move to right window, the left window should receive cancel.
1421     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1422               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1423                                 ui::LogicalDisplayId::DEFAULT, {201, 100}))
1424             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1425 
1426     leftWindow->consumeMotionCancel();
1427     rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1428     wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
1429 }
1430 
1431 /**
1432  * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1433  * interactive, it might stop sending this flag.
1434  * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1435  * to have a consistent input stream.
1436  *
1437  * Test procedure:
1438  * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1439  * DOWN (new gesture).
1440  *
1441  * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1442  * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1443  *
1444  * We technically just need a single window here, but we are using two windows (spy on top and a
1445  * regular window below) to emulate the actual situation where it happens on the device.
1446  */
TEST_F(InputDispatcherTest,TwoPointerCancelInconsistentPolicy)1447 TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1448     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1449     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1450                                                                 ui::LogicalDisplayId::DEFAULT);
1451     spyWindow->setFrame(Rect(0, 0, 200, 200));
1452     spyWindow->setTrustedOverlay(true);
1453     spyWindow->setSpy(true);
1454 
1455     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1456                                                              ui::LogicalDisplayId::DEFAULT);
1457     window->setFrame(Rect(0, 0, 200, 200));
1458 
1459     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
1460     const int32_t touchDeviceId = 4;
1461 
1462     // Two pointers down
1463     mDispatcher->notifyMotion(
1464             MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1465                     .deviceId(touchDeviceId)
1466                     .policyFlags(DEFAULT_POLICY_FLAGS)
1467                     .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1468                     .build());
1469 
1470     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1471                                       .deviceId(touchDeviceId)
1472                                       .policyFlags(DEFAULT_POLICY_FLAGS)
1473                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1474                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1475                                       .build());
1476     spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1477     spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1478     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1479     window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1480 
1481     // Cancel the current gesture. Send the cancel without the default policy flags.
1482     mDispatcher->notifyMotion(
1483             MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1484                     .deviceId(touchDeviceId)
1485                     .policyFlags(0)
1486                     .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1487                     .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1488                     .build());
1489     spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1490     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1491 
1492     // We don't need to reset the device to reproduce the issue, but the reset event typically
1493     // follows, so we keep it here to model the actual listener behaviour more closely.
1494     mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
1495 
1496     // Start new gesture
1497     mDispatcher->notifyMotion(
1498             MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1499                     .deviceId(touchDeviceId)
1500                     .policyFlags(DEFAULT_POLICY_FLAGS)
1501                     .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1502                     .build());
1503     spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1504     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1505 
1506     // No more events
1507     spyWindow->assertNoEvents();
1508     window->assertNoEvents();
1509 }
1510 
1511 /**
1512  * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1513  * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1514  * interactive, it might stop sending this flag.
1515  * We've already ensured the consistency of the touch event in this case, and we should also ensure
1516  * the consistency of the hover event in this case.
1517  *
1518  * Test procedure:
1519  * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1520  * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1521  *
1522  * We expect to receive two full streams of hover events.
1523  */
TEST_F(InputDispatcherTest,HoverEventInconsistentPolicy)1524 TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1525     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1526 
1527     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1528                                                              ui::LogicalDisplayId::DEFAULT);
1529     window->setFrame(Rect(0, 0, 300, 300));
1530 
1531     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1532 
1533     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1534                                       .policyFlags(DEFAULT_POLICY_FLAGS)
1535                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1536                                       .build());
1537     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1538 
1539     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1540                                       .policyFlags(DEFAULT_POLICY_FLAGS)
1541                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1542                                       .build());
1543     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1544 
1545     // Send hover exit without the default policy flags.
1546     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1547                                       .policyFlags(0)
1548                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1549                                       .build());
1550 
1551     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1552 
1553     // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1554     // right event.
1555     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1556                                       .policyFlags(DEFAULT_POLICY_FLAGS)
1557                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1558                                       .build());
1559     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1560 
1561     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1562                                       .policyFlags(DEFAULT_POLICY_FLAGS)
1563                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1564                                       .build());
1565     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1566 
1567     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1568                                       .policyFlags(DEFAULT_POLICY_FLAGS)
1569                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1570                                       .build());
1571     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1572 }
1573 
1574 /**
1575  * Two windows: a window on the left and a window on the right.
1576  * Mouse is hovered from the right window into the left window.
1577  * Next, we tap on the left window, where the cursor was last seen.
1578  * The second tap is done onto the right window.
1579  * The mouse and tap are from two different devices.
1580  * We technically don't need to set the downtime / eventtime for these events, but setting these
1581  * explicitly helps during debugging.
1582  * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1583  * In the buggy implementation, a tap on the right window would cause a crash.
1584  */
TEST_F(InputDispatcherTest,HoverFromLeftToRightAndTap_legacy)1585 TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1586     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1587 
1588     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1589     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1590                                                                  ui::LogicalDisplayId::DEFAULT);
1591     leftWindow->setFrame(Rect(0, 0, 200, 200));
1592 
1593     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1594                                                                   ui::LogicalDisplayId::DEFAULT);
1595     rightWindow->setFrame(Rect(200, 0, 400, 200));
1596 
1597     mDispatcher->onWindowInfosChanged(
1598             {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1599     // All times need to start at the current time, otherwise the dispatcher will drop the events as
1600     // stale.
1601     const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1602     const int32_t mouseDeviceId = 6;
1603     const int32_t touchDeviceId = 4;
1604     // Move the cursor from right
1605     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1606               injectMotionEvent(*mDispatcher,
1607                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1608                                                    AINPUT_SOURCE_MOUSE)
1609                                         .deviceId(mouseDeviceId)
1610                                         .downTime(baseTime + 10)
1611                                         .eventTime(baseTime + 20)
1612                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1613                                         .build()));
1614     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1615 
1616     // .. to the left window
1617     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1618               injectMotionEvent(*mDispatcher,
1619                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1620                                                    AINPUT_SOURCE_MOUSE)
1621                                         .deviceId(mouseDeviceId)
1622                                         .downTime(baseTime + 10)
1623                                         .eventTime(baseTime + 30)
1624                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1625                                         .build()));
1626     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1627     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1628     // Now tap the left window
1629     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1630               injectMotionEvent(*mDispatcher,
1631                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1632                                                    AINPUT_SOURCE_TOUCHSCREEN)
1633                                         .deviceId(touchDeviceId)
1634                                         .downTime(baseTime + 40)
1635                                         .eventTime(baseTime + 40)
1636                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1637                                         .build()));
1638     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1639     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1640 
1641     // release tap
1642     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1643               injectMotionEvent(*mDispatcher,
1644                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1645                                                    AINPUT_SOURCE_TOUCHSCREEN)
1646                                         .deviceId(touchDeviceId)
1647                                         .downTime(baseTime + 40)
1648                                         .eventTime(baseTime + 50)
1649                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1650                                         .build()));
1651     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1652 
1653     // Tap the window on the right
1654     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1655               injectMotionEvent(*mDispatcher,
1656                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1657                                                    AINPUT_SOURCE_TOUCHSCREEN)
1658                                         .deviceId(touchDeviceId)
1659                                         .downTime(baseTime + 60)
1660                                         .eventTime(baseTime + 60)
1661                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1662                                         .build()));
1663     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1664 
1665     // release tap
1666     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1667               injectMotionEvent(*mDispatcher,
1668                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1669                                                    AINPUT_SOURCE_TOUCHSCREEN)
1670                                         .deviceId(touchDeviceId)
1671                                         .downTime(baseTime + 60)
1672                                         .eventTime(baseTime + 70)
1673                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1674                                         .build()));
1675     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1676 
1677     // No more events
1678     leftWindow->assertNoEvents();
1679     rightWindow->assertNoEvents();
1680 }
1681 
1682 /**
1683  * Two windows: a window on the left and a window on the right.
1684  * Mouse is hovered from the right window into the left window.
1685  * Next, we tap on the left window, where the cursor was last seen.
1686  * The second tap is done onto the right window.
1687  * The mouse and tap are from two different devices.
1688  * We technically don't need to set the downtime / eventtime for these events, but setting these
1689  * explicitly helps during debugging.
1690  * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1691  * In the buggy implementation, a tap on the right window would cause a crash.
1692  */
TEST_F(InputDispatcherTest,HoverFromLeftToRightAndTap)1693 TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1694     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1695 
1696     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1697     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1698                                                                  ui::LogicalDisplayId::DEFAULT);
1699     leftWindow->setFrame(Rect(0, 0, 200, 200));
1700 
1701     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1702                                                                   ui::LogicalDisplayId::DEFAULT);
1703     rightWindow->setFrame(Rect(200, 0, 400, 200));
1704 
1705     mDispatcher->onWindowInfosChanged(
1706             {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1707     // All times need to start at the current time, otherwise the dispatcher will drop the events as
1708     // stale.
1709     const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1710     const int32_t mouseDeviceId = 6;
1711     const int32_t touchDeviceId = 4;
1712     // Move the cursor from right
1713     mDispatcher->notifyMotion(
1714             MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1715                     .deviceId(mouseDeviceId)
1716                     .downTime(baseTime + 10)
1717                     .eventTime(baseTime + 20)
1718                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1719                     .build());
1720     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1721 
1722     // .. to the left window
1723     mDispatcher->notifyMotion(
1724             MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1725                     .deviceId(mouseDeviceId)
1726                     .downTime(baseTime + 10)
1727                     .eventTime(baseTime + 30)
1728                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1729                     .build());
1730     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1731     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1732     // Now tap the left window
1733     mDispatcher->notifyMotion(
1734             MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1735                     .deviceId(touchDeviceId)
1736                     .downTime(baseTime + 40)
1737                     .eventTime(baseTime + 40)
1738                     .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1739                     .build());
1740     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1741 
1742     // release tap
1743     mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1744                                       .deviceId(touchDeviceId)
1745                                       .downTime(baseTime + 40)
1746                                       .eventTime(baseTime + 50)
1747                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1748                                       .build());
1749     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1750 
1751     // Tap the window on the right
1752     mDispatcher->notifyMotion(
1753             MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1754                     .deviceId(touchDeviceId)
1755                     .downTime(baseTime + 60)
1756                     .eventTime(baseTime + 60)
1757                     .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1758                     .build());
1759     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1760 
1761     // release tap
1762     mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1763                                       .deviceId(touchDeviceId)
1764                                       .downTime(baseTime + 60)
1765                                       .eventTime(baseTime + 70)
1766                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1767                                       .build());
1768     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1769 
1770     // No more events
1771     leftWindow->assertNoEvents();
1772     rightWindow->assertNoEvents();
1773 }
1774 
1775 /**
1776  * Start hovering in a window. While this hover is still active, make another window appear on top.
1777  * The top, obstructing window has no input channel, so it's not supposed to receive input.
1778  * While the top window is present, the hovering is stopped.
1779  * Later, hovering gets resumed again.
1780  * Ensure that new hover gesture is handled correctly.
1781  * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1782  * to the window that's currently being hovered over.
1783  */
TEST_F(InputDispatcherTest,HoverWhileWindowAppears)1784 TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1785     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1786     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1787                                                              ui::LogicalDisplayId::DEFAULT);
1788     window->setFrame(Rect(0, 0, 200, 200));
1789 
1790     // Only a single window is present at first
1791     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1792 
1793     // Start hovering in the window
1794     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1795                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1796                                       .build());
1797     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1798 
1799     // Now, an obscuring window appears!
1800     sp<FakeWindowHandle> obscuringWindow =
1801             sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
1802                                        ui::LogicalDisplayId::DEFAULT,
1803                                        /*createInputChannel=*/false);
1804     obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1805     obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1806     obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1807     obscuringWindow->setNoInputChannel(true);
1808     obscuringWindow->setFocusable(false);
1809     obscuringWindow->setAlpha(1.0);
1810     mDispatcher->onWindowInfosChanged(
1811             {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
1812 
1813     // While this new obscuring window is present, the hovering is stopped
1814     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1815                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1816                                       .build());
1817     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1818 
1819     // Now the obscuring window goes away.
1820     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1821 
1822     // And a new hover gesture starts.
1823     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1824                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1825                                       .build());
1826     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1827 }
1828 
1829 /**
1830  * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1831  * the obscuring window.
1832  */
TEST_F(InputDispatcherTest,HoverMoveWhileWindowAppears)1833 TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1834     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1835     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1836                                                              ui::LogicalDisplayId::DEFAULT);
1837     window->setFrame(Rect(0, 0, 200, 200));
1838 
1839     // Only a single window is present at first
1840     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1841 
1842     // Start hovering in the window
1843     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1844                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1845                                       .build());
1846     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1847 
1848     // Now, an obscuring window appears!
1849     sp<FakeWindowHandle> obscuringWindow =
1850             sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
1851                                        ui::LogicalDisplayId::DEFAULT,
1852                                        /*createInputChannel=*/false);
1853     obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1854     obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1855     obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1856     obscuringWindow->setNoInputChannel(true);
1857     obscuringWindow->setFocusable(false);
1858     obscuringWindow->setAlpha(1.0);
1859     mDispatcher->onWindowInfosChanged(
1860             {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
1861 
1862     // While this new obscuring window is present, the hovering continues. The event can't go to the
1863     // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1864     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1865                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1866                                       .build());
1867     obscuringWindow->assertNoEvents();
1868     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1869 
1870     // Now the obscuring window goes away.
1871     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1872 
1873     // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1874     // so it should generate a HOVER_ENTER
1875     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1876                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1877                                       .build());
1878     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1879 
1880     // Now the MOVE should be getting dispatched normally
1881     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1882                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1883                                       .build());
1884     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1885 }
1886 
1887 /**
1888  * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1889  * events are delivered to the window.
1890  */
TEST_F(InputDispatcherTest,HoverMoveAndScroll)1891 TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1892     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1893     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1894                                                              ui::LogicalDisplayId::DEFAULT);
1895     window->setFrame(Rect(0, 0, 200, 200));
1896     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1897 
1898     // Start hovering in the window
1899     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1900                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1901                                       .build());
1902     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1903 
1904     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1905                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1906                                       .build());
1907     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1908 
1909     // Scroll with the mouse
1910     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1911                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1912                                       .build());
1913     window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1914 }
1915 
1916 /**
1917  * Two windows: a trusted overlay and a regular window underneath. Both windows are visible.
1918  * Mouse is hovered, and the hover event should only go to the overlay.
1919  * However, next, the touchable region of the trusted overlay shrinks. The mouse position hasn't
1920  * changed, but the cursor would now end up hovering above the regular window underneatch.
1921  * If the mouse is now clicked, this would generate an ACTION_DOWN event, which would go to the
1922  * regular window. However, the trusted overlay is also watching for outside touch.
1923  * The trusted overlay should get two events:
1924  * 1) The ACTION_OUTSIDE event, since the click is now not inside its touchable region
1925  * 2) The HOVER_EXIT event, since the mouse pointer is no longer hovering inside this window
1926  *
1927  * This test reproduces a crash where there is an overlap between dispatch modes for the trusted
1928  * overlay touch target, since the event is causing both an ACTION_OUTSIDE, and as a HOVER_EXIT.
1929  */
TEST_F(InputDispatcherTest,MouseClickUnderShrinkingTrustedOverlay)1930 TEST_F(InputDispatcherTest, MouseClickUnderShrinkingTrustedOverlay) {
1931     std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
1932     sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(app, mDispatcher, "Trusted overlay",
1933                                                               ui::LogicalDisplayId::DEFAULT);
1934     overlay->setTrustedOverlay(true);
1935     overlay->setWatchOutsideTouch(true);
1936     overlay->setFrame(Rect(0, 0, 200, 200));
1937 
1938     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(app, mDispatcher, "Regular window",
1939                                                              ui::LogicalDisplayId::DEFAULT);
1940     window->setFrame(Rect(0, 0, 200, 200));
1941 
1942     mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1943     // Hover the mouse into the overlay
1944     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1945                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1946                                       .build());
1947     overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1948 
1949     // Now, shrink the touchable region of the overlay! This will cause the cursor to suddenly have
1950     // the regular window as the touch target
1951     overlay->setTouchableRegion(Region({0, 0, 0, 0}));
1952     mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1953 
1954     // Now we can click with the mouse. The click should go into the regular window
1955     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1956                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1957                                       .build());
1958     overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1959     overlay->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
1960     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1961 }
1962 
1963 /**
1964  * Similar to above, but also has a spy on top that also catches the HOVER
1965  * events. Also, instead of ACTION_DOWN, we are continuing to send the hovering
1966  * stream to ensure that the spy receives hover events correctly.
1967  */
TEST_F(InputDispatcherTest,MouseClickUnderShrinkingTrustedOverlayWithSpy)1968 TEST_F(InputDispatcherTest, MouseClickUnderShrinkingTrustedOverlayWithSpy) {
1969     std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
1970     sp<FakeWindowHandle> spyWindow =
1971             sp<FakeWindowHandle>::make(app, mDispatcher, "Spy", ui::LogicalDisplayId::DEFAULT);
1972     spyWindow->setFrame(Rect(0, 0, 200, 200));
1973     spyWindow->setTrustedOverlay(true);
1974     spyWindow->setSpy(true);
1975     sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(app, mDispatcher, "Trusted overlay",
1976                                                               ui::LogicalDisplayId::DEFAULT);
1977     overlay->setTrustedOverlay(true);
1978     overlay->setWatchOutsideTouch(true);
1979     overlay->setFrame(Rect(0, 0, 200, 200));
1980 
1981     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(app, mDispatcher, "Regular window",
1982                                                              ui::LogicalDisplayId::DEFAULT);
1983     window->setFrame(Rect(0, 0, 200, 200));
1984 
1985     mDispatcher->onWindowInfosChanged(
1986             {{*spyWindow->getInfo(), *overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1987     // Hover the mouse into the overlay
1988     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1989                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1990                                       .build());
1991     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1992     overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1993 
1994     // Now, shrink the touchable region of the overlay! This will cause the cursor to suddenly have
1995     // the regular window as the touch target
1996     overlay->setTouchableRegion(Region({0, 0, 0, 0}));
1997     mDispatcher->onWindowInfosChanged(
1998             {{*spyWindow->getInfo(), *overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1999 
2000     // Now we can click with the mouse. The click should go into the regular window
2001     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2002                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2003                                       .build());
2004     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2005     overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2006     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2007 }
2008 
2009 using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2010 
2011 /**
2012  * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2013  * touch is dropped, because stylus should be preferred over touch.
2014  */
TEST_F(InputDispatcherMultiDeviceTest,StylusDownBlocksTouchDown)2015 TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
2016     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
2017     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2018     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2019                                                              ui::LogicalDisplayId::DEFAULT);
2020     window->setFrame(Rect(0, 0, 200, 200));
2021 
2022     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2023 
2024     constexpr int32_t touchDeviceId = 4;
2025     constexpr int32_t stylusDeviceId = 2;
2026 
2027     // Stylus down
2028     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2029                                       .deviceId(stylusDeviceId)
2030                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2031                                       .build());
2032     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2033 
2034     // Touch down
2035     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2036                                       .deviceId(touchDeviceId)
2037                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2038                                       .build());
2039 
2040     // Touch move
2041     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2042                                       .deviceId(touchDeviceId)
2043                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2044                                       .build());
2045     // Touch is ignored because stylus is already down
2046 
2047     // Subsequent stylus movements are delivered correctly
2048     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2049                                       .deviceId(stylusDeviceId)
2050                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2051                                       .build());
2052     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2053                                      WithCoords(101, 111)));
2054 
2055     window->assertNoEvents();
2056 }
2057 
2058 /**
2059  * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2060  * touch is not dropped, because multiple devices are allowed to be active in the same window.
2061  */
TEST_F(InputDispatcherMultiDeviceTest,StylusDownDoesNotBlockTouchDown)2062 TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
2063     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2064     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2065     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2066                                                              ui::LogicalDisplayId::DEFAULT);
2067     window->setFrame(Rect(0, 0, 200, 200));
2068 
2069     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2070 
2071     constexpr int32_t touchDeviceId = 4;
2072     constexpr int32_t stylusDeviceId = 2;
2073 
2074     // Stylus down
2075     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2076                                       .deviceId(stylusDeviceId)
2077                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2078                                       .build());
2079     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2080 
2081     // Touch down
2082     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2083                                       .deviceId(touchDeviceId)
2084                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2085                                       .build());
2086     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2087 
2088     // Touch move
2089     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2090                                       .deviceId(touchDeviceId)
2091                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2092                                       .build());
2093     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2094 
2095     // Stylus move
2096     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2097                                       .deviceId(stylusDeviceId)
2098                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2099                                       .build());
2100     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2101                                      WithCoords(101, 111)));
2102 
2103     window->assertNoEvents();
2104 }
2105 
2106 /**
2107  * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2108  * down. Ensure that touch is dropped, because stylus should be preferred over touch.
2109  * Similar test as above, but with added SPY window.
2110  */
TEST_F(InputDispatcherMultiDeviceTest,StylusDownWithSpyBlocksTouchDown)2111 TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
2112     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
2113     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2114     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2115                                                              ui::LogicalDisplayId::DEFAULT);
2116     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2117                                                                 ui::LogicalDisplayId::DEFAULT);
2118     spyWindow->setFrame(Rect(0, 0, 200, 200));
2119     spyWindow->setTrustedOverlay(true);
2120     spyWindow->setSpy(true);
2121     window->setFrame(Rect(0, 0, 200, 200));
2122 
2123     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2124 
2125     constexpr int32_t touchDeviceId = 4;
2126     constexpr int32_t stylusDeviceId = 2;
2127 
2128     // Stylus down
2129     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2130                                       .deviceId(stylusDeviceId)
2131                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2132                                       .build());
2133     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2134     spyWindow->consumeMotionEvent(
2135             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2136 
2137     // Touch down
2138     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2139                                       .deviceId(touchDeviceId)
2140                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2141                                       .build());
2142 
2143     // Touch move
2144     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2145                                       .deviceId(touchDeviceId)
2146                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2147                                       .build());
2148 
2149     // Touch is ignored because stylus is already down
2150 
2151     // Subsequent stylus movements are delivered correctly
2152     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2153                                       .deviceId(stylusDeviceId)
2154                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2155                                       .build());
2156     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2157                                      WithCoords(101, 111)));
2158     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2159                                         WithCoords(101, 111)));
2160 
2161     window->assertNoEvents();
2162     spyWindow->assertNoEvents();
2163 }
2164 
2165 /**
2166  * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2167  * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2168  * Similar test as above, but with added SPY window.
2169  */
TEST_F(InputDispatcherMultiDeviceTest,StylusDownWithSpyDoesNotBlockTouchDown)2170 TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2171     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2172     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2173     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2174                                                              ui::LogicalDisplayId::DEFAULT);
2175     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2176                                                                 ui::LogicalDisplayId::DEFAULT);
2177     spyWindow->setFrame(Rect(0, 0, 200, 200));
2178     spyWindow->setTrustedOverlay(true);
2179     spyWindow->setSpy(true);
2180     window->setFrame(Rect(0, 0, 200, 200));
2181 
2182     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2183 
2184     constexpr int32_t touchDeviceId = 4;
2185     constexpr int32_t stylusDeviceId = 2;
2186 
2187     // Stylus down
2188     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2189                                       .deviceId(stylusDeviceId)
2190                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2191                                       .build());
2192     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2193     spyWindow->consumeMotionEvent(
2194             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2195 
2196     // Touch down
2197     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2198                                       .deviceId(touchDeviceId)
2199                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2200                                       .build());
2201     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2202     spyWindow->consumeMotionEvent(
2203             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2204 
2205     // Touch move
2206     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2207                                       .deviceId(touchDeviceId)
2208                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2209                                       .build());
2210     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2211     spyWindow->consumeMotionEvent(
2212             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2213 
2214     // Subsequent stylus movements are delivered correctly
2215     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2216                                       .deviceId(stylusDeviceId)
2217                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2218                                       .build());
2219     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2220                                      WithCoords(101, 111)));
2221     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2222                                         WithCoords(101, 111)));
2223 
2224     window->assertNoEvents();
2225     spyWindow->assertNoEvents();
2226 }
2227 
2228 /**
2229  * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2230  * touch is dropped, because stylus hover takes precedence.
2231  */
TEST_F(InputDispatcherMultiDeviceTest,StylusHoverBlocksTouchDown)2232 TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
2233     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
2234     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2235     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2236                                                              ui::LogicalDisplayId::DEFAULT);
2237     window->setFrame(Rect(0, 0, 200, 200));
2238 
2239     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2240 
2241     constexpr int32_t touchDeviceId = 4;
2242     constexpr int32_t stylusDeviceId = 2;
2243 
2244     // Stylus down on the window
2245     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2246                                       .deviceId(stylusDeviceId)
2247                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2248                                       .build());
2249     window->consumeMotionEvent(
2250             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2251 
2252     // Touch down on window
2253     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2254                                       .deviceId(touchDeviceId)
2255                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2256                                       .build());
2257     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2258                                       .deviceId(touchDeviceId)
2259                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2260                                       .build());
2261 
2262     // Touch is ignored because stylus is hovering
2263 
2264     // Subsequent stylus movements are delivered correctly
2265     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2266                                       .deviceId(stylusDeviceId)
2267                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2268                                       .build());
2269     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2270                                      WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2271 
2272     // and subsequent touches continue to be ignored
2273     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2274                                       .deviceId(touchDeviceId)
2275                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2276                                       .build());
2277     window->assertNoEvents();
2278 }
2279 
2280 /**
2281  * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2282  * touch is not dropped, because stylus hover and touch can be both active at the same time.
2283  */
TEST_F(InputDispatcherMultiDeviceTest,StylusHoverDoesNotBlockTouchDown)2284 TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2285     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2286     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2287     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2288                                                              ui::LogicalDisplayId::DEFAULT);
2289     window->setFrame(Rect(0, 0, 200, 200));
2290 
2291     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2292 
2293     constexpr int32_t touchDeviceId = 4;
2294     constexpr int32_t stylusDeviceId = 2;
2295 
2296     // Stylus down on the window
2297     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2298                                       .deviceId(stylusDeviceId)
2299                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2300                                       .build());
2301     window->consumeMotionEvent(
2302             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2303 
2304     // Touch down on window
2305     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2306                                       .deviceId(touchDeviceId)
2307                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2308                                       .build());
2309     // Touch move on window
2310     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2311     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2312                                       .deviceId(touchDeviceId)
2313                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2314                                       .build());
2315     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2316 
2317     // Subsequent stylus movements are delivered correctly
2318     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2319                                       .deviceId(stylusDeviceId)
2320                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2321                                       .build());
2322     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2323                                      WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2324 
2325     // and subsequent touches continue to work
2326     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2327                                       .deviceId(touchDeviceId)
2328                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2329                                       .build());
2330     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2331     window->assertNoEvents();
2332 }
2333 
2334 /**
2335  * One window. Touch down on the window. Then, stylus hover on the window from another device.
2336  * Ensure that touch is canceled, because stylus hover should take precedence.
2337  */
TEST_F(InputDispatcherMultiDeviceTest,TouchIsCanceledByStylusHover)2338 TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
2339     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
2340     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2341     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2342                                                              ui::LogicalDisplayId::DEFAULT);
2343     window->setFrame(Rect(0, 0, 200, 200));
2344 
2345     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2346 
2347     constexpr int32_t touchDeviceId = 4;
2348     constexpr int32_t stylusDeviceId = 2;
2349 
2350     // Touch down on window
2351     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2352                                       .deviceId(touchDeviceId)
2353                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2354                                       .build());
2355     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2356                                       .deviceId(touchDeviceId)
2357                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2358                                       .build());
2359     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2360     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2361 
2362     // Stylus hover on the window
2363     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2364                                       .deviceId(stylusDeviceId)
2365                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2366                                       .build());
2367     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2368                                       .deviceId(stylusDeviceId)
2369                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2370                                       .build());
2371     // Stylus hover movement causes touch to be canceled
2372     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2373                                      WithCoords(141, 146)));
2374     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2375                                      WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2376     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2377                                      WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2378 
2379     // Subsequent touch movements are ignored
2380     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2381                                       .deviceId(touchDeviceId)
2382                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2383                                       .build());
2384 
2385     window->assertNoEvents();
2386 }
2387 
2388 /**
2389  * One window. Touch down on the window. Then, stylus hover on the window from another device.
2390  * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2391  */
TEST_F(InputDispatcherMultiDeviceTest,TouchIsNotCanceledByStylusHover)2392 TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2393     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2394     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2395     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2396                                                              ui::LogicalDisplayId::DEFAULT);
2397     window->setFrame(Rect(0, 0, 200, 200));
2398 
2399     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2400 
2401     constexpr int32_t touchDeviceId = 4;
2402     constexpr int32_t stylusDeviceId = 2;
2403 
2404     // Touch down on window
2405     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2406                                       .deviceId(touchDeviceId)
2407                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2408                                       .build());
2409     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2410                                       .deviceId(touchDeviceId)
2411                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2412                                       .build());
2413     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2414     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2415 
2416     // Stylus hover on the window
2417     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2418                                       .deviceId(stylusDeviceId)
2419                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2420                                       .build());
2421     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2422                                       .deviceId(stylusDeviceId)
2423                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2424                                       .build());
2425     // Stylus hover movement is received normally
2426     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2427                                      WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2428     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2429                                      WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2430 
2431     // Subsequent touch movements also work
2432     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2433                                       .deviceId(touchDeviceId)
2434                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2435                                       .build());
2436     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2437                                      WithCoords(142, 147)));
2438 
2439     window->assertNoEvents();
2440 }
2441 
2442 /**
2443  * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2444  * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2445  * become active.
2446  */
TEST_F(InputDispatcherMultiDeviceTest,LatestStylusWins)2447 TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2448     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
2449     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2450     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2451                                                              ui::LogicalDisplayId::DEFAULT);
2452     window->setFrame(Rect(0, 0, 200, 200));
2453 
2454     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2455 
2456     constexpr int32_t stylusDeviceId1 = 3;
2457     constexpr int32_t stylusDeviceId2 = 5;
2458 
2459     // Touch down on window
2460     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2461                                       .deviceId(stylusDeviceId1)
2462                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2463                                       .build());
2464     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2465                                       .deviceId(stylusDeviceId1)
2466                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2467                                       .build());
2468     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2469     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2470 
2471     // Second stylus down
2472     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2473                                       .deviceId(stylusDeviceId2)
2474                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2475                                       .build());
2476     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2477                                       .deviceId(stylusDeviceId2)
2478                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2479                                       .build());
2480 
2481     // First stylus is canceled, second one takes over.
2482     window->consumeMotionEvent(
2483             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2484     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2485     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2486 
2487     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2488                                       .deviceId(stylusDeviceId1)
2489                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2490                                       .build());
2491     // Subsequent stylus movements are delivered correctly
2492     window->assertNoEvents();
2493 }
2494 
2495 /**
2496  * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2497  * both stylus devices can function simultaneously.
2498  */
TEST_F(InputDispatcherMultiDeviceTest,TwoStylusDevicesActiveAtTheSameTime)2499 TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2500     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2501     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2502     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2503                                                              ui::LogicalDisplayId::DEFAULT);
2504     window->setFrame(Rect(0, 0, 200, 200));
2505 
2506     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2507 
2508     constexpr int32_t stylusDeviceId1 = 3;
2509     constexpr int32_t stylusDeviceId2 = 5;
2510 
2511     // Touch down on window
2512     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2513                                       .deviceId(stylusDeviceId1)
2514                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2515                                       .build());
2516     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2517                                       .deviceId(stylusDeviceId1)
2518                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2519                                       .build());
2520     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2521     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2522 
2523     // Second stylus down
2524     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2525                                       .deviceId(stylusDeviceId2)
2526                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2527                                       .build());
2528     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2529                                       .deviceId(stylusDeviceId2)
2530                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2531                                       .build());
2532     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2533     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2534 
2535     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2536                                       .deviceId(stylusDeviceId1)
2537                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2538                                       .build());
2539     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2540     window->assertNoEvents();
2541 }
2542 
2543 /**
2544  * One window. Touch down on the window. Then, stylus down on the window from another device.
2545  * Ensure that is canceled, because stylus down should be preferred over touch.
2546  */
TEST_F(InputDispatcherMultiDeviceTest,TouchIsCanceledByStylusDown)2547 TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2548     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
2549     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2550     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2551                                                              ui::LogicalDisplayId::DEFAULT);
2552     window->setFrame(Rect(0, 0, 200, 200));
2553 
2554     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2555 
2556     constexpr int32_t touchDeviceId = 4;
2557     constexpr int32_t stylusDeviceId = 2;
2558 
2559     // Touch down on window
2560     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2561                                       .deviceId(touchDeviceId)
2562                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2563                                       .build());
2564     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2565                                       .deviceId(touchDeviceId)
2566                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2567                                       .build());
2568     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2569     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2570 
2571     // Stylus down on the window
2572     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2573                                       .deviceId(stylusDeviceId)
2574                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2575                                       .build());
2576     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2577     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2578 
2579     // Subsequent stylus movements are delivered correctly
2580     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2581                                       .deviceId(stylusDeviceId)
2582                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2583                                       .build());
2584     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2585                                      WithCoords(101, 111)));
2586 }
2587 
2588 /**
2589  * One window. Touch down on the window. Then, stylus down on the window from another device.
2590  * Ensure that both touch and stylus are functioning independently.
2591  */
TEST_F(InputDispatcherMultiDeviceTest,TouchIsNotCanceledByStylusDown)2592 TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2593     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2594     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2595     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2596                                                              ui::LogicalDisplayId::DEFAULT);
2597     window->setFrame(Rect(0, 0, 200, 200));
2598 
2599     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2600 
2601     constexpr int32_t touchDeviceId = 4;
2602     constexpr int32_t stylusDeviceId = 2;
2603 
2604     // Touch down on window
2605     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2606                                       .deviceId(touchDeviceId)
2607                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2608                                       .build());
2609     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2610                                       .deviceId(touchDeviceId)
2611                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2612                                       .build());
2613     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2614     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2615 
2616     // Stylus down on the window
2617     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2618                                       .deviceId(stylusDeviceId)
2619                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2620                                       .build());
2621     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2622 
2623     // Subsequent stylus movements are delivered correctly
2624     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2625                                       .deviceId(stylusDeviceId)
2626                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2627                                       .build());
2628     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2629                                      WithCoords(101, 111)));
2630 
2631     // Touch continues to work too
2632     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2633                                       .deviceId(touchDeviceId)
2634                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2635                                       .build());
2636     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2637 }
2638 
2639 /**
2640  * Two windows: a window on the left and a window on the right.
2641  * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2642  * down. Then, on the left window, also place second touch pointer down.
2643  * This test tries to reproduce a crash.
2644  * In the buggy implementation, second pointer down on the left window would cause a crash.
2645  */
TEST_F(InputDispatcherMultiDeviceTest,MultiDeviceSplitTouch_legacy)2646 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2647     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
2648     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2649     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2650                                                                  ui::LogicalDisplayId::DEFAULT);
2651     leftWindow->setFrame(Rect(0, 0, 200, 200));
2652 
2653     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2654                                                                   ui::LogicalDisplayId::DEFAULT);
2655     rightWindow->setFrame(Rect(200, 0, 400, 200));
2656 
2657     mDispatcher->onWindowInfosChanged(
2658             {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2659 
2660     const int32_t touchDeviceId = 4;
2661     const int32_t mouseDeviceId = 6;
2662 
2663     // Start hovering over the left window
2664     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2665                                       .deviceId(mouseDeviceId)
2666                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2667                                       .build());
2668     leftWindow->consumeMotionEvent(
2669             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2670 
2671     // Mouse down on left window
2672     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2673                                       .deviceId(mouseDeviceId)
2674                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2675                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2676                                       .build());
2677 
2678     leftWindow->consumeMotionEvent(
2679             AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2680     leftWindow->consumeMotionEvent(
2681             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2682 
2683     mDispatcher->notifyMotion(
2684             MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2685                     .deviceId(mouseDeviceId)
2686                     .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2687                     .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2688                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2689                     .build());
2690     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2691 
2692     // First touch pointer down on right window
2693     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2694                                       .deviceId(touchDeviceId)
2695                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2696                                       .build());
2697     leftWindow->assertNoEvents();
2698 
2699     rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2700 
2701     // Second touch pointer down on left window
2702     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2703                                       .deviceId(touchDeviceId)
2704                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2705                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2706                                       .build());
2707     // Since this is now a new splittable pointer going down on the left window, and it's coming
2708     // from a different device, the current gesture in the left window (pointer down) should first
2709     // be canceled.
2710     leftWindow->consumeMotionEvent(
2711             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
2712     leftWindow->consumeMotionEvent(
2713             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2714     // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2715     // current implementation.
2716     const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2717     rightWindow->consumeMotionEvent(
2718             AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2719 
2720     leftWindow->assertNoEvents();
2721     rightWindow->assertNoEvents();
2722 }
2723 
2724 /**
2725  * Two windows: a window on the left and a window on the right.
2726  * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2727  * down. Then, on the left window, also place second touch pointer down.
2728  * This test tries to reproduce a crash.
2729  * In the buggy implementation, second pointer down on the left window would cause a crash.
2730  */
TEST_F(InputDispatcherMultiDeviceTest,MultiDeviceSplitTouch)2731 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2732     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2733     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2734     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2735                                                                  ui::LogicalDisplayId::DEFAULT);
2736     leftWindow->setFrame(Rect(0, 0, 200, 200));
2737 
2738     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2739                                                                   ui::LogicalDisplayId::DEFAULT);
2740     rightWindow->setFrame(Rect(200, 0, 400, 200));
2741 
2742     mDispatcher->onWindowInfosChanged(
2743             {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2744 
2745     const int32_t touchDeviceId = 4;
2746     const int32_t mouseDeviceId = 6;
2747 
2748     // Start hovering over the left window
2749     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2750                                       .deviceId(mouseDeviceId)
2751                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2752                                       .build());
2753     leftWindow->consumeMotionEvent(
2754             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2755 
2756     // Mouse down on left window
2757     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2758                                       .deviceId(mouseDeviceId)
2759                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2760                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2761                                       .build());
2762 
2763     leftWindow->consumeMotionEvent(
2764             AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2765     leftWindow->consumeMotionEvent(
2766             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2767 
2768     mDispatcher->notifyMotion(
2769             MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2770                     .deviceId(mouseDeviceId)
2771                     .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2772                     .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2773                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2774                     .build());
2775     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2776 
2777     // First touch pointer down on right window
2778     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2779                                       .deviceId(touchDeviceId)
2780                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2781                                       .build());
2782     leftWindow->assertNoEvents();
2783 
2784     rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2785 
2786     // Second touch pointer down on left window
2787     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2788                                       .deviceId(touchDeviceId)
2789                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2790                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2791                                       .build());
2792     // Since this is now a new splittable pointer going down on the left window, and it's coming
2793     // from a different device, it will be split and delivered to left window separately.
2794     leftWindow->consumeMotionEvent(
2795             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2796     // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2797     // current implementation.
2798     const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2799     rightWindow->consumeMotionEvent(
2800             AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2801 
2802     leftWindow->assertNoEvents();
2803     rightWindow->assertNoEvents();
2804 }
2805 
2806 /**
2807  * Two windows: a window on the left and a window on the right.
2808  * Mouse is hovered on the left window and stylus is hovered on the right window.
2809  */
TEST_F(InputDispatcherMultiDeviceTest,MultiDeviceHover)2810 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2811     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2812     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2813                                                                  ui::LogicalDisplayId::DEFAULT);
2814     leftWindow->setFrame(Rect(0, 0, 200, 200));
2815 
2816     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2817                                                                   ui::LogicalDisplayId::DEFAULT);
2818     rightWindow->setFrame(Rect(200, 0, 400, 200));
2819 
2820     mDispatcher->onWindowInfosChanged(
2821             {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2822 
2823     const int32_t stylusDeviceId = 3;
2824     const int32_t mouseDeviceId = 6;
2825 
2826     // Start hovering over the left window
2827     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2828                                       .deviceId(mouseDeviceId)
2829                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2830                                       .build());
2831     leftWindow->consumeMotionEvent(
2832             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2833 
2834     // Stylus hovered on right window
2835     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2836                                       .deviceId(stylusDeviceId)
2837                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2838                                       .build());
2839     rightWindow->consumeMotionEvent(
2840             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2841 
2842     // Subsequent HOVER_MOVE events are dispatched correctly.
2843     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2844                                       .deviceId(mouseDeviceId)
2845                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2846                                       .build());
2847     leftWindow->consumeMotionEvent(
2848             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
2849 
2850     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2851                                       .deviceId(stylusDeviceId)
2852                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2853                                       .build());
2854     rightWindow->consumeMotionEvent(
2855             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
2856 
2857     leftWindow->assertNoEvents();
2858     rightWindow->assertNoEvents();
2859 }
2860 
2861 /**
2862  * Three windows: a window on the left and a window on the right.
2863  * And a spy window that's positioned above all of them.
2864  * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2865  * Check the stream that's received by the spy.
2866  */
TEST_F(InputDispatcherMultiDeviceTest,MultiDeviceWithSpy_legacy)2867 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2868     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
2869     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2870 
2871     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2872                                                                 ui::LogicalDisplayId::DEFAULT);
2873     spyWindow->setFrame(Rect(0, 0, 400, 400));
2874     spyWindow->setTrustedOverlay(true);
2875     spyWindow->setSpy(true);
2876 
2877     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2878                                                                  ui::LogicalDisplayId::DEFAULT);
2879     leftWindow->setFrame(Rect(0, 0, 200, 200));
2880 
2881     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2882                                                                   ui::LogicalDisplayId::DEFAULT);
2883 
2884     rightWindow->setFrame(Rect(200, 0, 400, 200));
2885 
2886     mDispatcher->onWindowInfosChanged(
2887             {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2888 
2889     const int32_t stylusDeviceId = 1;
2890     const int32_t touchDeviceId = 2;
2891 
2892     // Stylus down on the left window
2893     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2894                                       .deviceId(stylusDeviceId)
2895                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2896                                       .build());
2897     leftWindow->consumeMotionEvent(
2898             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2899     spyWindow->consumeMotionEvent(
2900             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2901 
2902     // Touch down on the right window
2903     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2904                                       .deviceId(touchDeviceId)
2905                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2906                                       .build());
2907     leftWindow->assertNoEvents();
2908     rightWindow->consumeMotionEvent(
2909             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2910 
2911     // Spy window does not receive touch events, because stylus events take precedence, and it
2912     // already has an active stylus gesture.
2913 
2914     // Stylus movements continue. They should be delivered to the left window and to the spy window
2915     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2916                                       .deviceId(stylusDeviceId)
2917                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2918                                       .build());
2919     leftWindow->consumeMotionEvent(
2920             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2921     spyWindow->consumeMotionEvent(
2922             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2923 
2924     // Further MOVE events keep going to the right window only
2925     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2926                                       .deviceId(touchDeviceId)
2927                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2928                                       .build());
2929     rightWindow->consumeMotionEvent(
2930             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2931 
2932     spyWindow->assertNoEvents();
2933     leftWindow->assertNoEvents();
2934     rightWindow->assertNoEvents();
2935 }
2936 
2937 /**
2938  * Three windows: a window on the left and a window on the right.
2939  * And a spy window that's positioned above all of them.
2940  * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2941  * Check the stream that's received by the spy.
2942  */
TEST_F(InputDispatcherMultiDeviceTest,MultiDeviceWithSpy)2943 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2944     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2945     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2946 
2947     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2948                                                                 ui::LogicalDisplayId::DEFAULT);
2949     spyWindow->setFrame(Rect(0, 0, 400, 400));
2950     spyWindow->setTrustedOverlay(true);
2951     spyWindow->setSpy(true);
2952 
2953     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2954                                                                  ui::LogicalDisplayId::DEFAULT);
2955     leftWindow->setFrame(Rect(0, 0, 200, 200));
2956 
2957     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2958                                                                   ui::LogicalDisplayId::DEFAULT);
2959 
2960     rightWindow->setFrame(Rect(200, 0, 400, 200));
2961 
2962     mDispatcher->onWindowInfosChanged(
2963             {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2964 
2965     const int32_t stylusDeviceId = 1;
2966     const int32_t touchDeviceId = 2;
2967 
2968     // Stylus down on the left window
2969     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2970                                       .deviceId(stylusDeviceId)
2971                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2972                                       .build());
2973     leftWindow->consumeMotionEvent(
2974             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2975     spyWindow->consumeMotionEvent(
2976             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2977 
2978     // Touch down on the right window
2979     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2980                                       .deviceId(touchDeviceId)
2981                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2982                                       .build());
2983     leftWindow->assertNoEvents();
2984     rightWindow->consumeMotionEvent(
2985             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2986     spyWindow->consumeMotionEvent(
2987             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2988 
2989     // Stylus movements continue. They should be delivered to the left window and to the spy window
2990     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2991                                       .deviceId(stylusDeviceId)
2992                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2993                                       .build());
2994     leftWindow->consumeMotionEvent(
2995             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2996     spyWindow->consumeMotionEvent(
2997             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2998 
2999     // Further touch MOVE events keep going to the right window and to the spy
3000     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3001                                       .deviceId(touchDeviceId)
3002                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3003                                       .build());
3004     rightWindow->consumeMotionEvent(
3005             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3006     spyWindow->consumeMotionEvent(
3007             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3008 
3009     spyWindow->assertNoEvents();
3010     leftWindow->assertNoEvents();
3011     rightWindow->assertNoEvents();
3012 }
3013 
3014 /**
3015  * Three windows: a window on the left, a window on the right, and a spy window positioned above
3016  * both.
3017  * Check hover in left window and touch down in the right window.
3018  * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
3019  * At the same time, left and right should be getting independent streams of hovering and touch,
3020  * respectively.
3021  */
TEST_F(InputDispatcherMultiDeviceTest,MultiDeviceHoverBlocksTouchWithSpy)3022 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
3023     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
3024     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3025 
3026     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3027                                                                 ui::LogicalDisplayId::DEFAULT);
3028     spyWindow->setFrame(Rect(0, 0, 400, 400));
3029     spyWindow->setTrustedOverlay(true);
3030     spyWindow->setSpy(true);
3031 
3032     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3033                                                                  ui::LogicalDisplayId::DEFAULT);
3034     leftWindow->setFrame(Rect(0, 0, 200, 200));
3035 
3036     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3037                                                                   ui::LogicalDisplayId::DEFAULT);
3038     rightWindow->setFrame(Rect(200, 0, 400, 200));
3039 
3040     mDispatcher->onWindowInfosChanged(
3041             {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3042 
3043     const int32_t stylusDeviceId = 1;
3044     const int32_t touchDeviceId = 2;
3045 
3046     // Stylus hover on the left window
3047     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3048                                       .deviceId(stylusDeviceId)
3049                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3050                                       .build());
3051     leftWindow->consumeMotionEvent(
3052             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3053     spyWindow->consumeMotionEvent(
3054             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3055 
3056     // Touch down on the right window. Spy doesn't receive this touch because it already has
3057     // stylus hovering there.
3058     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3059                                       .deviceId(touchDeviceId)
3060                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3061                                       .build());
3062     leftWindow->assertNoEvents();
3063     spyWindow->assertNoEvents();
3064     rightWindow->consumeMotionEvent(
3065             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3066 
3067     // Stylus movements continue. They should be delivered to the left window and the spy.
3068     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3069                                       .deviceId(stylusDeviceId)
3070                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3071                                       .build());
3072     leftWindow->consumeMotionEvent(
3073             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3074     spyWindow->consumeMotionEvent(
3075             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3076 
3077     // Touch movements continue. They should be delivered to the right window only
3078     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3079                                       .deviceId(touchDeviceId)
3080                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3081                                       .build());
3082     rightWindow->consumeMotionEvent(
3083             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3084 
3085     spyWindow->assertNoEvents();
3086     leftWindow->assertNoEvents();
3087     rightWindow->assertNoEvents();
3088 }
3089 
3090 /**
3091  * Three windows: a window on the left, a window on the right, and a spy window positioned above
3092  * both.
3093  * Check hover in left window and touch down in the right window.
3094  * At first, spy should receive hover. Next, spy should receive touch.
3095  * At the same time, left and right should be getting independent streams of hovering and touch,
3096  * respectively.
3097  */
TEST_F(InputDispatcherMultiDeviceTest,MultiDeviceHoverDoesNotBlockTouchWithSpy)3098 TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3099     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3100     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3101 
3102     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3103                                                                 ui::LogicalDisplayId::DEFAULT);
3104     spyWindow->setFrame(Rect(0, 0, 400, 400));
3105     spyWindow->setTrustedOverlay(true);
3106     spyWindow->setSpy(true);
3107 
3108     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3109                                                                  ui::LogicalDisplayId::DEFAULT);
3110     leftWindow->setFrame(Rect(0, 0, 200, 200));
3111 
3112     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3113                                                                   ui::LogicalDisplayId::DEFAULT);
3114     rightWindow->setFrame(Rect(200, 0, 400, 200));
3115 
3116     mDispatcher->onWindowInfosChanged(
3117             {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3118 
3119     const int32_t stylusDeviceId = 1;
3120     const int32_t touchDeviceId = 2;
3121 
3122     // Stylus hover on the left window
3123     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3124                                       .deviceId(stylusDeviceId)
3125                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3126                                       .build());
3127     leftWindow->consumeMotionEvent(
3128             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3129     spyWindow->consumeMotionEvent(
3130             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3131 
3132     // Touch down on the right window.
3133     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3134                                       .deviceId(touchDeviceId)
3135                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3136                                       .build());
3137     leftWindow->assertNoEvents();
3138     spyWindow->consumeMotionEvent(
3139             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3140     rightWindow->consumeMotionEvent(
3141             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3142 
3143     // Stylus movements continue. They should be delivered to the left window and the spy.
3144     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3145                                       .deviceId(stylusDeviceId)
3146                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3147                                       .build());
3148     leftWindow->consumeMotionEvent(
3149             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3150     spyWindow->consumeMotionEvent(
3151             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3152 
3153     // Touch movements continue. They should be delivered to the right window and the spy
3154     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3155                                       .deviceId(touchDeviceId)
3156                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3157                                       .build());
3158     rightWindow->consumeMotionEvent(
3159             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3160     spyWindow->consumeMotionEvent(
3161             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3162 
3163     spyWindow->assertNoEvents();
3164     leftWindow->assertNoEvents();
3165     rightWindow->assertNoEvents();
3166 }
3167 
3168 /**
3169  * On a single window, use two different devices: mouse and touch.
3170  * Touch happens first, with two pointers going down, and then the first pointer leaving.
3171  * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3172  * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3173  * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3174  * represent a new gesture.
3175  */
TEST_F(InputDispatcherMultiDeviceTest,MixedTouchAndMouseWithPointerDown_legacy)3176 TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3177     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
3178     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3179     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3180                                                              ui::LogicalDisplayId::DEFAULT);
3181     window->setFrame(Rect(0, 0, 400, 400));
3182 
3183     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3184 
3185     const int32_t touchDeviceId = 4;
3186     const int32_t mouseDeviceId = 6;
3187 
3188     // First touch pointer down
3189     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3190                                       .deviceId(touchDeviceId)
3191                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3192                                       .build());
3193     // Second touch pointer down
3194     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3195                                       .deviceId(touchDeviceId)
3196                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3197                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3198                                       .build());
3199     // First touch pointer lifts. The second one remains down
3200     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3201                                       .deviceId(touchDeviceId)
3202                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3203                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3204                                       .build());
3205     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3206     window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3207     window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3208 
3209     // Mouse down. The touch should be canceled
3210     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3211                                       .deviceId(mouseDeviceId)
3212                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3213                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3214                                       .build());
3215 
3216     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3217                                      WithPointerCount(1u)));
3218     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3219 
3220     mDispatcher->notifyMotion(
3221             MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3222                     .deviceId(mouseDeviceId)
3223                     .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3224                     .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3225                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3226                     .build());
3227     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3228 
3229     // Second touch pointer down.
3230     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3231                                       .deviceId(touchDeviceId)
3232                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3233                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3234                                       .build());
3235     // Since we already canceled this touch gesture, it will be ignored until a completely new
3236     // gesture is started. This is easier to implement than trying to keep track of the new pointer
3237     // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3238     // However, mouse movements should continue to work.
3239     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3240                                       .deviceId(mouseDeviceId)
3241                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3242                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3243                                       .build());
3244     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3245 
3246     window->assertNoEvents();
3247 }
3248 
3249 /**
3250  * On a single window, use two different devices: mouse and touch.
3251  * Touch happens first, with two pointers going down, and then the first pointer leaving.
3252  * Mouse is clicked next, which should not interfere with the touch stream.
3253  * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3254  * delivered correctly.
3255  */
TEST_F(InputDispatcherMultiDeviceTest,MixedTouchAndMouseWithPointerDown)3256 TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3257     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3258     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3259     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3260                                                              ui::LogicalDisplayId::DEFAULT);
3261     window->setFrame(Rect(0, 0, 400, 400));
3262 
3263     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3264 
3265     const int32_t touchDeviceId = 4;
3266     const int32_t mouseDeviceId = 6;
3267 
3268     // First touch pointer down
3269     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3270                                       .deviceId(touchDeviceId)
3271                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3272                                       .build());
3273     // Second touch pointer down
3274     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3275                                       .deviceId(touchDeviceId)
3276                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3277                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3278                                       .build());
3279     // First touch pointer lifts. The second one remains down
3280     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3281                                       .deviceId(touchDeviceId)
3282                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3283                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3284                                       .build());
3285     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3286     window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3287     window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3288 
3289     // Mouse down
3290     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3291                                       .deviceId(mouseDeviceId)
3292                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3293                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3294                                       .build());
3295 
3296     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3297 
3298     mDispatcher->notifyMotion(
3299             MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3300                     .deviceId(mouseDeviceId)
3301                     .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3302                     .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3303                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3304                     .build());
3305     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3306 
3307     // Second touch pointer down.
3308     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3309                                       .deviceId(touchDeviceId)
3310                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3311                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3312                                       .build());
3313     window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3314                                      WithPointerCount(2u)));
3315 
3316     // Mouse movements should continue to work
3317     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3318                                       .deviceId(mouseDeviceId)
3319                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3320                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3321                                       .build());
3322     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3323 
3324     window->assertNoEvents();
3325 }
3326 
3327 /**
3328  * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3329  * the injected event.
3330  */
TEST_F(InputDispatcherMultiDeviceTest,UnfinishedInjectedEvent_legacy)3331 TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3332     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
3333     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3334     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3335                                                              ui::LogicalDisplayId::DEFAULT);
3336     window->setFrame(Rect(0, 0, 400, 400));
3337 
3338     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3339 
3340     const int32_t touchDeviceId = 4;
3341     // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3342     // completion.
3343     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3344               injectMotionEvent(*mDispatcher,
3345                                 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3346                                         .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3347                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3348                                         .build()));
3349     window->consumeMotionEvent(
3350             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3351 
3352     // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3353     // should be canceled and the new gesture should take over.
3354     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3355                                       .deviceId(touchDeviceId)
3356                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3357                                       .build());
3358 
3359     window->consumeMotionEvent(
3360             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3361     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3362 }
3363 
3364 /**
3365  * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3366  * parallel to the injected event.
3367  */
TEST_F(InputDispatcherMultiDeviceTest,UnfinishedInjectedEvent)3368 TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3369     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3370     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3371     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3372                                                              ui::LogicalDisplayId::DEFAULT);
3373     window->setFrame(Rect(0, 0, 400, 400));
3374 
3375     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3376 
3377     const int32_t touchDeviceId = 4;
3378     // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3379     // completion.
3380     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3381               injectMotionEvent(*mDispatcher,
3382                                 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3383                                         .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3384                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3385                                         .build()));
3386     window->consumeMotionEvent(
3387             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3388 
3389     // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3390     // allowed through.
3391     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3392                                       .deviceId(touchDeviceId)
3393                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3394                                       .build());
3395     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3396 }
3397 
3398 /**
3399  * This test is similar to the test above, but the sequence of injected events is different.
3400  *
3401  * Two windows: a window on the left and a window on the right.
3402  * Mouse is hovered over the left window.
3403  * Next, we tap on the left window, where the cursor was last seen.
3404  *
3405  * After that, we inject one finger down onto the right window, and then a second finger down onto
3406  * the left window.
3407  * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3408  * window (first), and then another on the left window (second).
3409  * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3410  * In the buggy implementation, second finger down on the left window would cause a crash.
3411  */
TEST_F(InputDispatcherMultiDeviceTest,HoverTapAndSplitTouch_legacy)3412 TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3413     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
3414     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3415     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3416                                                                  ui::LogicalDisplayId::DEFAULT);
3417     leftWindow->setFrame(Rect(0, 0, 200, 200));
3418 
3419     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3420                                                                   ui::LogicalDisplayId::DEFAULT);
3421     rightWindow->setFrame(Rect(200, 0, 400, 200));
3422 
3423     mDispatcher->onWindowInfosChanged(
3424             {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3425 
3426     const int32_t mouseDeviceId = 6;
3427     const int32_t touchDeviceId = 4;
3428     // Hover over the left window. Keep the cursor there.
3429     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3430               injectMotionEvent(*mDispatcher,
3431                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3432                                                    AINPUT_SOURCE_MOUSE)
3433                                         .deviceId(mouseDeviceId)
3434                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3435                                         .build()));
3436     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3437 
3438     // Tap on left window
3439     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3440               injectMotionEvent(*mDispatcher,
3441                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3442                                                    AINPUT_SOURCE_TOUCHSCREEN)
3443                                         .deviceId(touchDeviceId)
3444                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3445                                         .build()));
3446 
3447     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3448               injectMotionEvent(*mDispatcher,
3449                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3450                                                    AINPUT_SOURCE_TOUCHSCREEN)
3451                                         .deviceId(touchDeviceId)
3452                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3453                                         .build()));
3454     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3455     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3456     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3457 
3458     // First finger down on right window
3459     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3460               injectMotionEvent(*mDispatcher,
3461                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3462                                                    AINPUT_SOURCE_TOUCHSCREEN)
3463                                         .deviceId(touchDeviceId)
3464                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3465                                         .build()));
3466     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3467 
3468     // Second finger down on the left window
3469     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3470               injectMotionEvent(*mDispatcher,
3471                                 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3472                                         .deviceId(touchDeviceId)
3473                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3474                                         .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3475                                         .build()));
3476     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3477     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3478 
3479     // No more events
3480     leftWindow->assertNoEvents();
3481     rightWindow->assertNoEvents();
3482 }
3483 
3484 /**
3485  * This test is similar to the test above, but the sequence of injected events is different.
3486  *
3487  * Two windows: a window on the left and a window on the right.
3488  * Mouse is hovered over the left window.
3489  * Next, we tap on the left window, where the cursor was last seen.
3490  *
3491  * After that, we send one finger down onto the right window, and then a second finger down onto
3492  * the left window.
3493  * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3494  * window (first), and then another on the left window (second).
3495  * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3496  * In the buggy implementation, second finger down on the left window would cause a crash.
3497  */
TEST_F(InputDispatcherMultiDeviceTest,HoverTapAndSplitTouch)3498 TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3499     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3500     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3501     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3502                                                                  ui::LogicalDisplayId::DEFAULT);
3503     leftWindow->setFrame(Rect(0, 0, 200, 200));
3504 
3505     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3506                                                                   ui::LogicalDisplayId::DEFAULT);
3507     rightWindow->setFrame(Rect(200, 0, 400, 200));
3508 
3509     mDispatcher->onWindowInfosChanged(
3510             {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3511 
3512     const int32_t mouseDeviceId = 6;
3513     const int32_t touchDeviceId = 4;
3514     // Hover over the left window. Keep the cursor there.
3515     mDispatcher->notifyMotion(
3516             MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3517                     .deviceId(mouseDeviceId)
3518                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3519                     .build());
3520     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3521 
3522     // Tap on left window
3523     mDispatcher->notifyMotion(
3524             MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3525                     .deviceId(touchDeviceId)
3526                     .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3527                     .build());
3528 
3529     mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3530                                       .deviceId(touchDeviceId)
3531                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3532                                       .build());
3533     leftWindow->consumeMotionEvent(
3534             AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3535     leftWindow->consumeMotionEvent(
3536             AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3537 
3538     // First finger down on right window
3539     mDispatcher->notifyMotion(
3540             MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3541                     .deviceId(touchDeviceId)
3542                     .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3543                     .build());
3544     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3545 
3546     // Second finger down on the left window
3547     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3548                                       .deviceId(touchDeviceId)
3549                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3550                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3551                                       .build());
3552     leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3553     rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3554 
3555     // No more events
3556     leftWindow->assertNoEvents();
3557     rightWindow->assertNoEvents();
3558 }
3559 
3560 /**
3561  * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3562  * While the touch is down, new hover events from the stylus device should be ignored. After the
3563  * touch is gone, stylus hovering should start working again.
3564  */
TEST_F(InputDispatcherMultiDeviceTest,StylusHoverIgnoresTouchTap)3565 TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
3566     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
3567     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3568     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3569                                                              ui::LogicalDisplayId::DEFAULT);
3570     window->setFrame(Rect(0, 0, 200, 200));
3571 
3572     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3573 
3574     const int32_t stylusDeviceId = 5;
3575     const int32_t touchDeviceId = 4;
3576     // Start hovering with stylus
3577     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3578               injectMotionEvent(*mDispatcher,
3579                                 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3580                                         .deviceId(stylusDeviceId)
3581                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3582                                         .build()));
3583     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3584 
3585     // Finger down on the window
3586     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3587               injectMotionEvent(*mDispatcher,
3588                                 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3589                                         .deviceId(touchDeviceId)
3590                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3591                                         .build()));
3592     // The touch device should be ignored!
3593 
3594     // Continue hovering with stylus.
3595     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3596               injectMotionEvent(*mDispatcher,
3597                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3598                                                    AINPUT_SOURCE_STYLUS)
3599                                         .deviceId(stylusDeviceId)
3600                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3601                                         .build()));
3602     // Hovers continue to work
3603     window->consumeMotionEvent(
3604             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3605 
3606     // Lift up the finger
3607     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3608               injectMotionEvent(*mDispatcher,
3609                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3610                                                    AINPUT_SOURCE_TOUCHSCREEN)
3611                                         .deviceId(touchDeviceId)
3612                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3613                                         .build()));
3614 
3615     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3616               injectMotionEvent(*mDispatcher,
3617                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3618                                                    AINPUT_SOURCE_STYLUS)
3619                                         .deviceId(stylusDeviceId)
3620                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3621                                         .build()));
3622     window->consumeMotionEvent(
3623             AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3624     window->assertNoEvents();
3625 }
3626 
3627 /**
3628  * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3629  * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3630  * check that the stylus hovering continues to work.
3631  */
TEST_F(InputDispatcherMultiDeviceTest,StylusHoverWithTouchTap)3632 TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3633     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3634     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3635     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3636                                                              ui::LogicalDisplayId::DEFAULT);
3637     window->setFrame(Rect(0, 0, 200, 200));
3638 
3639     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3640 
3641     const int32_t stylusDeviceId = 5;
3642     const int32_t touchDeviceId = 4;
3643     // Start hovering with stylus
3644     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3645                                       .deviceId(stylusDeviceId)
3646                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3647                                       .build());
3648     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3649 
3650     // Finger down on the window
3651     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3652                                       .deviceId(touchDeviceId)
3653                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3654                                       .build());
3655     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3656 
3657     // Continue hovering with stylus.
3658     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3659                                       .deviceId(stylusDeviceId)
3660                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3661                                       .build());
3662     // Hovers continue to work
3663     window->consumeMotionEvent(
3664             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3665 
3666     // Lift up the finger
3667     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3668                                       .deviceId(touchDeviceId)
3669                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3670                                       .build());
3671     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3672 
3673     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3674                                       .deviceId(stylusDeviceId)
3675                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3676                                       .build());
3677     window->consumeMotionEvent(
3678             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3679     window->assertNoEvents();
3680 }
3681 
3682 /**
3683  * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3684  * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3685  *
3686  * Two windows: one on the left and one on the right.
3687  * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3688  * Stylus down on the left window, and then touch down on the right window.
3689  * Check that the right window doesn't get touches while the stylus is down on the left window.
3690  */
TEST_F(InputDispatcherMultiDeviceTest,GlobalStylusDownBlocksTouch)3691 TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3692     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3693     sp<FakeWindowHandle> leftWindow =
3694             sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3695                                        ui::LogicalDisplayId::DEFAULT);
3696     leftWindow->setFrame(Rect(0, 0, 100, 100));
3697 
3698     sp<FakeWindowHandle> sbtRightWindow =
3699             sp<FakeWindowHandle>::make(application, mDispatcher,
3700                                        "Stylus blocks touch (right) window",
3701                                        ui::LogicalDisplayId::DEFAULT);
3702     sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3703     sbtRightWindow->setGlobalStylusBlocksTouch(true);
3704 
3705     mDispatcher->onWindowInfosChanged(
3706             {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3707 
3708     const int32_t stylusDeviceId = 5;
3709     const int32_t touchDeviceId = 4;
3710 
3711     // Stylus down in the left window
3712     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3713                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3714                                       .deviceId(stylusDeviceId)
3715                                       .build());
3716     leftWindow->consumeMotionEvent(
3717             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3718 
3719     // Finger tap on the right window
3720     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3721                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3722                                       .deviceId(touchDeviceId)
3723                                       .build());
3724     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3725                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3726                                       .deviceId(touchDeviceId)
3727                                       .build());
3728 
3729     // The touch should be blocked, because stylus is down somewhere else on screen!
3730     sbtRightWindow->assertNoEvents();
3731 
3732     // Continue stylus motion, and ensure it's not impacted.
3733     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3734                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3735                                       .deviceId(stylusDeviceId)
3736                                       .build());
3737     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3738                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3739                                       .deviceId(stylusDeviceId)
3740                                       .build());
3741     leftWindow->consumeMotionEvent(
3742             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3743     leftWindow->consumeMotionEvent(
3744             AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3745 
3746     // Now that the stylus gesture is done, touches should be getting delivered correctly.
3747     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3748                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3749                                       .deviceId(touchDeviceId)
3750                                       .build());
3751     sbtRightWindow->consumeMotionEvent(
3752             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3753 }
3754 
3755 /**
3756  * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3757  * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3758  *
3759  * Two windows: one on the left and one on the right.
3760  * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3761  * Stylus hover on the left window, and then touch down on the right window.
3762  * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3763  */
TEST_F(InputDispatcherMultiDeviceTest,GlobalStylusHoverBlocksTouch)3764 TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3765     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3766     sp<FakeWindowHandle> leftWindow =
3767             sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3768                                        ui::LogicalDisplayId::DEFAULT);
3769     leftWindow->setFrame(Rect(0, 0, 100, 100));
3770 
3771     sp<FakeWindowHandle> sbtRightWindow =
3772             sp<FakeWindowHandle>::make(application, mDispatcher,
3773                                        "Stylus blocks touch (right) window",
3774                                        ui::LogicalDisplayId::DEFAULT);
3775     sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3776     sbtRightWindow->setGlobalStylusBlocksTouch(true);
3777 
3778     mDispatcher->onWindowInfosChanged(
3779             {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3780 
3781     const int32_t stylusDeviceId = 5;
3782     const int32_t touchDeviceId = 4;
3783 
3784     // Stylus hover in the left window
3785     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3786                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3787                                       .deviceId(stylusDeviceId)
3788                                       .build());
3789     leftWindow->consumeMotionEvent(
3790             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3791 
3792     // Finger tap on the right window
3793     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3794                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3795                                       .deviceId(touchDeviceId)
3796                                       .build());
3797     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3798                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3799                                       .deviceId(touchDeviceId)
3800                                       .build());
3801 
3802     // The touch should be blocked, because stylus is hovering somewhere else on screen!
3803     sbtRightWindow->assertNoEvents();
3804 
3805     // Continue stylus motion, and ensure it's not impacted.
3806     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3807                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3808                                       .deviceId(stylusDeviceId)
3809                                       .build());
3810     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3811                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3812                                       .deviceId(stylusDeviceId)
3813                                       .build());
3814     leftWindow->consumeMotionEvent(
3815             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3816     leftWindow->consumeMotionEvent(
3817             AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3818 
3819     // Now that the stylus gesture is done, touches should be getting delivered correctly.
3820     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3821                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3822                                       .deviceId(touchDeviceId)
3823                                       .build());
3824     sbtRightWindow->consumeMotionEvent(
3825             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3826 }
3827 
3828 /**
3829  * A spy window above a window with no input channel.
3830  * Start hovering with a stylus device, and then tap with it.
3831  * Ensure spy window receives the entire sequence.
3832  */
TEST_F(InputDispatcherTest,StylusHoverAndDownNoInputChannel)3833 TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3834     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3835     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3836                                                                 ui::LogicalDisplayId::DEFAULT);
3837     spyWindow->setFrame(Rect(0, 0, 200, 200));
3838     spyWindow->setTrustedOverlay(true);
3839     spyWindow->setSpy(true);
3840     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3841                                                              ui::LogicalDisplayId::DEFAULT);
3842     window->setNoInputChannel(true);
3843     window->setFrame(Rect(0, 0, 200, 200));
3844 
3845     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
3846 
3847     // Start hovering with stylus
3848     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3849                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3850                                       .build());
3851     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3852     // Stop hovering
3853     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3854                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3855                                       .build());
3856     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3857 
3858     // Stylus touches down
3859     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3860                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3861                                       .build());
3862     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3863 
3864     // Stylus goes up
3865     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3866                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3867                                       .build());
3868     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3869 
3870     // Again hover
3871     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3872                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3873                                       .build());
3874     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3875     // Stop hovering
3876     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3877                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3878                                       .build());
3879     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3880 
3881     // No more events
3882     spyWindow->assertNoEvents();
3883     window->assertNoEvents();
3884 }
3885 
3886 /**
3887  * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3888  * rejected. But since we already have an ongoing gesture, this event should be processed.
3889  * This prevents inconsistent events being handled inside the dispatcher.
3890  */
TEST_F(InputDispatcherTest,StaleStylusHoverGestureIsComplete)3891 TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3892     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3893 
3894     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3895                                                              ui::LogicalDisplayId::DEFAULT);
3896     window->setFrame(Rect(0, 0, 200, 200));
3897 
3898     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3899 
3900     // Start hovering with stylus
3901     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3902                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3903                                       .build());
3904     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3905 
3906     NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3907                                          .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3908                                          .build();
3909     // Make this 'hoverExit' event stale
3910     mFakePolicy->setStaleEventTimeout(100ms);
3911     std::this_thread::sleep_for(100ms);
3912 
3913     // It shouldn't be dropped by the dispatcher, even though it's stale.
3914     mDispatcher->notifyMotion(hoverExit);
3915     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3916 
3917     // Stylus starts hovering again! There should be no crash.
3918     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3919                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3920                                       .build());
3921     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3922 }
3923 
3924 /**
3925  * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3926  * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3927  * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3928  * While the mouse is down, new move events from the touch device should be ignored.
3929  */
TEST_F(InputDispatcherTest,TouchPilferAndMouseMove_legacy)3930 TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3931     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
3932     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3933     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3934                                                                 ui::LogicalDisplayId::DEFAULT);
3935     spyWindow->setFrame(Rect(0, 0, 200, 200));
3936     spyWindow->setTrustedOverlay(true);
3937     spyWindow->setSpy(true);
3938     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3939                                                              ui::LogicalDisplayId::DEFAULT);
3940     window->setFrame(Rect(0, 0, 200, 200));
3941 
3942     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
3943 
3944     const int32_t mouseDeviceId = 7;
3945     const int32_t touchDeviceId = 4;
3946 
3947     // Hover a bit with mouse first
3948     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3949                                       .deviceId(mouseDeviceId)
3950                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3951                                       .build());
3952     spyWindow->consumeMotionEvent(
3953             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3954     window->consumeMotionEvent(
3955             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3956 
3957     // Start touching
3958     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3959                                       .deviceId(touchDeviceId)
3960                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3961                                       .build());
3962     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3963     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3964     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3965     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3966 
3967     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3968                                       .deviceId(touchDeviceId)
3969                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3970                                       .build());
3971     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3972     window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3973 
3974     // Pilfer the stream
3975     EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3976     window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3977 
3978     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3979                                       .deviceId(touchDeviceId)
3980                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3981                                       .build());
3982     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3983 
3984     // Mouse down
3985     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3986                                       .deviceId(mouseDeviceId)
3987                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3988                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3989                                       .build());
3990 
3991     spyWindow->consumeMotionEvent(
3992             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3993     spyWindow->consumeMotionEvent(
3994             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3995     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3996 
3997     mDispatcher->notifyMotion(
3998             MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3999                     .deviceId(mouseDeviceId)
4000                     .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4001                     .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4002                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4003                     .build());
4004     spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4005     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4006 
4007     // Mouse move!
4008     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4009                                       .deviceId(mouseDeviceId)
4010                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4011                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4012                                       .build());
4013     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4014     window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4015 
4016     // Touch move!
4017     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4018                                       .deviceId(touchDeviceId)
4019                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4020                                       .build());
4021 
4022     // No more events
4023     spyWindow->assertNoEvents();
4024     window->assertNoEvents();
4025 }
4026 
4027 /**
4028  * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
4029  * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
4030  * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
4031  * While the mouse is down, new move events from the touch device should continue to work.
4032  */
TEST_F(InputDispatcherTest,TouchPilferAndMouseMove)4033 TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
4034     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4035     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4036     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4037                                                                 ui::LogicalDisplayId::DEFAULT);
4038     spyWindow->setFrame(Rect(0, 0, 200, 200));
4039     spyWindow->setTrustedOverlay(true);
4040     spyWindow->setSpy(true);
4041     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4042                                                              ui::LogicalDisplayId::DEFAULT);
4043     window->setFrame(Rect(0, 0, 200, 200));
4044 
4045     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4046 
4047     const int32_t mouseDeviceId = 7;
4048     const int32_t touchDeviceId = 4;
4049 
4050     // Hover a bit with mouse first
4051     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4052                                       .deviceId(mouseDeviceId)
4053                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4054                                       .build());
4055     spyWindow->consumeMotionEvent(
4056             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4057     window->consumeMotionEvent(
4058             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4059 
4060     // Start touching
4061     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4062                                       .deviceId(touchDeviceId)
4063                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4064                                       .build());
4065 
4066     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4067     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4068 
4069     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4070                                       .deviceId(touchDeviceId)
4071                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
4072                                       .build());
4073     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4074     window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4075 
4076     // Pilfer the stream
4077     EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4078     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
4079     // Hover is not pilfered! Only touch.
4080 
4081     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4082                                       .deviceId(touchDeviceId)
4083                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
4084                                       .build());
4085     spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4086 
4087     // Mouse down
4088     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4089                                       .deviceId(mouseDeviceId)
4090                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4091                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4092                                       .build());
4093 
4094     spyWindow->consumeMotionEvent(
4095             AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4096     spyWindow->consumeMotionEvent(
4097             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4098     window->consumeMotionEvent(
4099             AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4100     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4101 
4102     mDispatcher->notifyMotion(
4103             MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4104                     .deviceId(mouseDeviceId)
4105                     .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4106                     .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4107                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4108                     .build());
4109     spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4110     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4111 
4112     // Mouse move!
4113     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4114                                       .deviceId(mouseDeviceId)
4115                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4116                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4117                                       .build());
4118     spyWindow->consumeMotionEvent(
4119             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4120     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4121 
4122     // Touch move!
4123     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4124                                       .deviceId(touchDeviceId)
4125                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4126                                       .build());
4127     spyWindow->consumeMotionEvent(
4128             AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4129 
4130     // No more events
4131     spyWindow->assertNoEvents();
4132     window->assertNoEvents();
4133 }
4134 
4135 /**
4136  * On the display, have a single window, and also an area where there's no window.
4137  * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4138  * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4139  */
TEST_F(InputDispatcherTest,SplitWorksWhenEmptyAreaIsTouched)4140 TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4141     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4142     sp<FakeWindowHandle> window =
4143             sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
4144 
4145     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4146 
4147     // Touch down on the empty space
4148     mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
4149 
4150     mDispatcher->waitForIdle();
4151     window->assertNoEvents();
4152 
4153     // Now touch down on the window with another pointer
4154     mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
4155     mDispatcher->waitForIdle();
4156     window->consumeMotionDown();
4157 }
4158 
4159 /**
4160  * Same test as above, but instead of touching the empty space, the first touch goes to
4161  * non-touchable window.
4162  */
TEST_F(InputDispatcherTest,SplitWorksWhenNonTouchableWindowIsTouched)4163 TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4164     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4165     sp<FakeWindowHandle> window1 =
4166             sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4167     window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4168     window1->setTouchable(false);
4169     sp<FakeWindowHandle> window2 =
4170             sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4171     window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4172 
4173     mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4174 
4175     // Touch down on the non-touchable window
4176     mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
4177 
4178     mDispatcher->waitForIdle();
4179     window1->assertNoEvents();
4180     window2->assertNoEvents();
4181 
4182     // Now touch down on the window with another pointer
4183     mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
4184     mDispatcher->waitForIdle();
4185     window2->consumeMotionDown();
4186 }
4187 
4188 /**
4189  * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4190  * to the event time of the first ACTION_DOWN sent to the particular window.
4191  */
TEST_F(InputDispatcherTest,SplitTouchesSendCorrectActionDownTime)4192 TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4193     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4194     sp<FakeWindowHandle> window1 =
4195             sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4196     window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4197     sp<FakeWindowHandle> window2 =
4198             sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4199     window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4200 
4201     mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4202 
4203     // Touch down on the first window
4204     mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
4205     mDispatcher->waitForIdle();
4206 
4207     const std::unique_ptr<MotionEvent> firstDown =
4208             window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4209     ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
4210     window2->assertNoEvents();
4211 
4212     // Now touch down on the window with another pointer
4213     mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
4214     mDispatcher->waitForIdle();
4215 
4216     const std::unique_ptr<MotionEvent> secondDown =
4217             window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4218     ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4219     ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4220     // We currently send MOVE events to all windows receiving a split touch when there is any change
4221     // in the touch state, even when none of the pointers in the split window actually moved.
4222     // Document this behavior in the test.
4223     window1->consumeMotionMove();
4224 
4225     // Now move the pointer on the second window
4226     mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
4227     mDispatcher->waitForIdle();
4228 
4229     window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4230     window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4231 
4232     // Now add new touch down on the second window
4233     mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
4234     mDispatcher->waitForIdle();
4235 
4236     window2->consumeMotionEvent(
4237             AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4238     window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4239 
4240     // Now move the pointer on the first window
4241     mDispatcher->notifyMotion(
4242             generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
4243     mDispatcher->waitForIdle();
4244 
4245     window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4246     window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4247 
4248     // Now add new touch down on the first window
4249     mDispatcher->notifyMotion(
4250             generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
4251     mDispatcher->waitForIdle();
4252 
4253     window1->consumeMotionEvent(
4254             AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4255     window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4256 }
4257 
4258 /**
4259  * When events are not split, the downTime should be adjusted such that the downTime corresponds
4260  * to the event time of the first ACTION_DOWN. If a new window appears, it should not affect
4261  * the event routing because the first window prevents splitting.
4262  */
TEST_F(InputDispatcherTest,SplitTouchesSendCorrectActionDownTimeForNewWindow)4263 TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) {
4264     SCOPED_FLAG_OVERRIDE(split_all_touches, false);
4265     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4266     sp<FakeWindowHandle> window1 =
4267             sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4268     window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4269     window1->setPreventSplitting(true);
4270 
4271     sp<FakeWindowHandle> window2 =
4272             sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4273     window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4274 
4275     mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4276 
4277     // Touch down on the first window
4278     NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4279                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4280                                         .build();
4281     mDispatcher->notifyMotion(downArgs);
4282 
4283     window1->consumeMotionEvent(
4284             AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4285 
4286     // Second window is added
4287     mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4288 
4289     // Now touch down on the window with another pointer
4290     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4291                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4292                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4293                                       .downTime(downArgs.downTime)
4294                                       .build());
4295     window1->consumeMotionPointerDown(1, AllOf(WithDownTime(downArgs.downTime)));
4296 
4297     // Finish the gesture
4298     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4299                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4300                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4301                                       .downTime(downArgs.downTime)
4302                                       .build());
4303     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4304                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4305                                       .downTime(downArgs.downTime)
4306                                       .build());
4307     window1->consumeMotionPointerUp(1, AllOf(WithDownTime(downArgs.downTime)));
4308     window1->consumeMotionEvent(
4309             AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4310     window2->assertNoEvents();
4311 }
4312 
4313 /**
4314  * When splitting touch events, the downTime should be adjusted such that the downTime corresponds
4315  * to the event time of the first ACTION_DOWN sent to the new window.
4316  * If a new window that does not support split appears on the screen and gets touched with the
4317  * second finger, it should not get any events because it doesn't want split touches. At the same
4318  * time, the first window should not get the pointer_down event because it supports split touches
4319  * (and the touch occurred outside of the bounds of window1).
4320  */
TEST_F(InputDispatcherTest,SplitTouchesDropsEventForNonSplittableSecondWindow)4321 TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) {
4322     SCOPED_FLAG_OVERRIDE(split_all_touches, false);
4323     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4324     sp<FakeWindowHandle> window1 =
4325             sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4326     window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4327 
4328     sp<FakeWindowHandle> window2 =
4329             sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4330     window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4331 
4332     mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4333 
4334     // Touch down on the first window
4335     NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4336                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4337                                         .build();
4338     mDispatcher->notifyMotion(downArgs);
4339 
4340     window1->consumeMotionEvent(
4341             AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4342 
4343     // Second window is added
4344     window2->setPreventSplitting(true);
4345     mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4346 
4347     // Now touch down on the window with another pointer
4348     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4349                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4350                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4351                                       .downTime(downArgs.downTime)
4352                                       .build());
4353     // Event is dropped because window2 doesn't support split touch, and window1 does.
4354 
4355     // Complete the gesture
4356     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4357                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4358                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4359                                       .downTime(downArgs.downTime)
4360                                       .build());
4361     // A redundant MOVE event is generated that doesn't carry any new information
4362     window1->consumeMotionEvent(
4363             AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime)));
4364     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4365                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4366                                       .downTime(downArgs.downTime)
4367                                       .build());
4368 
4369     window1->consumeMotionEvent(
4370             AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4371     window1->assertNoEvents();
4372     window2->assertNoEvents();
4373 }
4374 
TEST_F(InputDispatcherTest,HoverMoveEnterMouseClickAndHoverMoveExit)4375 TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
4376     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4377     sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4378                                                                  ui::LogicalDisplayId::DEFAULT);
4379     windowLeft->setFrame(Rect(0, 0, 600, 800));
4380     sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4381                                                                   ui::LogicalDisplayId::DEFAULT);
4382     windowRight->setFrame(Rect(600, 0, 1200, 800));
4383 
4384     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4385 
4386     mDispatcher->onWindowInfosChanged(
4387             {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
4388 
4389     // Start cursor position in right window so that we can move the cursor to left window.
4390     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4391               injectMotionEvent(*mDispatcher,
4392                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4393                                                    AINPUT_SOURCE_MOUSE)
4394                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
4395                                         .build()));
4396     windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4397 
4398     // Move cursor into left window
4399     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4400               injectMotionEvent(*mDispatcher,
4401                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4402                                                    AINPUT_SOURCE_MOUSE)
4403                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4404                                         .build()));
4405     windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4406     windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4407 
4408     // Inject a series of mouse events for a mouse click
4409     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4410               injectMotionEvent(*mDispatcher,
4411                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4412                                         .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4413                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4414                                         .build()));
4415     windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4416     windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4417 
4418     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4419               injectMotionEvent(*mDispatcher,
4420                                 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4421                                                    AINPUT_SOURCE_MOUSE)
4422                                         .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4423                                         .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4424                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4425                                         .build()));
4426     windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4427 
4428     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4429               injectMotionEvent(*mDispatcher,
4430                                 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4431                                                    AINPUT_SOURCE_MOUSE)
4432                                         .buttonState(0)
4433                                         .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4434                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4435                                         .build()));
4436     windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
4437 
4438     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4439               injectMotionEvent(*mDispatcher,
4440                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4441                                         .buttonState(0)
4442                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4443                                         .build()));
4444     windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
4445 
4446     // Move mouse cursor back to right window
4447     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4448               injectMotionEvent(*mDispatcher,
4449                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4450                                                    AINPUT_SOURCE_MOUSE)
4451                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
4452                                         .build()));
4453     windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4454 
4455     // No more events
4456     windowLeft->assertNoEvents();
4457     windowRight->assertNoEvents();
4458 }
4459 
4460 /**
4461  * Put two fingers down (and don't release them) and click the mouse button.
4462  * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4463  * currently active gesture should be canceled, and the new one should proceed.
4464  */
TEST_F(InputDispatcherTest,TwoPointersDownMouseClick_legacy)4465 TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4466     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
4467     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4468     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4469                                                              ui::LogicalDisplayId::DEFAULT);
4470     window->setFrame(Rect(0, 0, 600, 800));
4471 
4472     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4473 
4474     const int32_t touchDeviceId = 4;
4475     const int32_t mouseDeviceId = 6;
4476 
4477     // Two pointers down
4478     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4479                                       .deviceId(touchDeviceId)
4480                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4481                                       .build());
4482 
4483     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4484                                       .deviceId(touchDeviceId)
4485                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4486                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4487                                       .build());
4488     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4489     window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4490 
4491     // Inject a series of mouse events for a mouse click
4492     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4493                                       .deviceId(mouseDeviceId)
4494                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4495                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4496                                       .build());
4497     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4498                                      WithPointerCount(2u)));
4499     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4500 
4501     mDispatcher->notifyMotion(
4502             MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4503                     .deviceId(mouseDeviceId)
4504                     .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4505                     .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4506                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4507                     .build());
4508     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4509 
4510     // Try to send more touch events while the mouse is down. Since it's a continuation of an
4511     // already canceled gesture, it should be ignored.
4512     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4513                                       .deviceId(touchDeviceId)
4514                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4515                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4516                                       .build());
4517     window->assertNoEvents();
4518 }
4519 
4520 /**
4521  * Put two fingers down (and don't release them) and click the mouse button.
4522  * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4523  * currently active gesture should not be canceled, and the new one should proceed in parallel.
4524  */
TEST_F(InputDispatcherTest,TwoPointersDownMouseClick)4525 TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4526     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4527     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4528     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4529                                                              ui::LogicalDisplayId::DEFAULT);
4530     window->setFrame(Rect(0, 0, 600, 800));
4531 
4532     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4533 
4534     const int32_t touchDeviceId = 4;
4535     const int32_t mouseDeviceId = 6;
4536 
4537     // Two pointers down
4538     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4539                                       .deviceId(touchDeviceId)
4540                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4541                                       .build());
4542 
4543     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4544                                       .deviceId(touchDeviceId)
4545                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4546                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4547                                       .build());
4548     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4549     window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4550 
4551     // Send a series of mouse events for a mouse click
4552     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4553                                       .deviceId(mouseDeviceId)
4554                                       .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4555                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4556                                       .build());
4557     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4558 
4559     mDispatcher->notifyMotion(
4560             MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4561                     .deviceId(mouseDeviceId)
4562                     .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4563                     .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4564                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4565                     .build());
4566     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4567 
4568     // Try to send more touch events while the mouse is down. Since it's a continuation of an
4569     // already active gesture, it should be sent normally.
4570     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4571                                       .deviceId(touchDeviceId)
4572                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4573                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4574                                       .build());
4575     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4576     window->assertNoEvents();
4577 }
4578 
4579 /**
4580  * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4581  * though the window underneath should not get any events.
4582  */
TEST_F(InputDispatcherTest,NonSplittableSpyAboveNoInputChannelWindowSinglePointer)4583 TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowSinglePointer) {
4584     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4585 
4586     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4587                                                                 ui::LogicalDisplayId::DEFAULT);
4588     spyWindow->setFrame(Rect(0, 0, 100, 100));
4589     spyWindow->setTrustedOverlay(true);
4590     spyWindow->setPreventSplitting(true);
4591     spyWindow->setSpy(true);
4592     // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4593     sp<FakeWindowHandle> inputSinkWindow =
4594             sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4595                                        ui::LogicalDisplayId::DEFAULT);
4596     inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4597     inputSinkWindow->setTrustedOverlay(true);
4598     inputSinkWindow->setPreventSplitting(true);
4599     inputSinkWindow->setNoInputChannel(true);
4600 
4601     mDispatcher->onWindowInfosChanged(
4602             {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4603 
4604     // Tap the spy window
4605     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4606                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4607                                       .build());
4608     mDispatcher->notifyMotion(
4609             MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4610                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4611                     .build());
4612 
4613     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4614     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4615     inputSinkWindow->assertNoEvents();
4616 }
4617 
4618 /**
4619  * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4620  * though the window underneath should not get any events.
4621  * Same test as above, but with two pointers touching instead of one.
4622  */
TEST_F(InputDispatcherTest,NonSplittableSpyAboveNoInputChannelWindowTwoPointers)4623 TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowTwoPointers) {
4624     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4625 
4626     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4627                                                                 ui::LogicalDisplayId::DEFAULT);
4628     spyWindow->setFrame(Rect(0, 0, 100, 100));
4629     spyWindow->setTrustedOverlay(true);
4630     spyWindow->setPreventSplitting(true);
4631     spyWindow->setSpy(true);
4632     // Another window below spy that would have both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4633     sp<FakeWindowHandle> inputSinkWindow =
4634             sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4635                                        ui::LogicalDisplayId::DEFAULT);
4636     inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4637     inputSinkWindow->setTrustedOverlay(true);
4638     inputSinkWindow->setPreventSplitting(true);
4639     inputSinkWindow->setNoInputChannel(true);
4640 
4641     mDispatcher->onWindowInfosChanged(
4642             {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4643 
4644     // Both fingers land into the spy window
4645     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4646                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4647                                       .build());
4648     mDispatcher->notifyMotion(
4649             MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4650                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4651                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4652                     .build());
4653     mDispatcher->notifyMotion(
4654             MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4655                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4656                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4657                     .build());
4658     mDispatcher->notifyMotion(
4659             MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4660                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4661                     .build());
4662 
4663     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4664     spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4665     spyWindow->consumeMotionPointerUp(1, WithPointerCount(2));
4666     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4667     inputSinkWindow->assertNoEvents();
4668 }
4669 
4670 /** Check the behaviour for cases where input sink prevents or doesn't prevent splitting. */
4671 class SpyThatPreventsSplittingWithApplicationFixture : public InputDispatcherTest,
4672                                                        public ::testing::WithParamInterface<bool> {
4673 };
4674 
4675 /**
4676  * Three windows:
4677  * - An application window (app window)
4678  * - A spy window that does not overlap the app window. Has PREVENT_SPLITTING flag
4679  * - A window below the spy that has NO_INPUT_CHANNEL (call it 'inputSink')
4680  *
4681  * The spy window is side-by-side with the app window. The inputSink is below the spy.
4682  * We first touch the area outside of the appWindow, but inside spyWindow.
4683  * Only the SPY window should get the DOWN event.
4684  * The spy pilfers after receiving the first DOWN event.
4685  * Next, we touch the app window.
4686  * The spy should receive POINTER_DOWN(1) (since spy is preventing splits).
4687  * Also, since the spy is already pilfering the first pointer, it will be sent the remaining new
4688  * pointers automatically, as well.
4689  * Next, the first pointer (from the spy) is lifted.
4690  * Spy should get POINTER_UP(0).
4691  * This event should not go to the app because the app never received this pointer to begin with.
4692  * Now, lift the remaining pointer and check that the spy receives UP event.
4693  *
4694  * Finally, send a new ACTION_DOWN event to the spy and check that it's received.
4695  * This test attempts to reproduce a crash in the dispatcher.
4696  */
TEST_P(SpyThatPreventsSplittingWithApplicationFixture,SpyThatPreventsSplittingWithApplication)4697 TEST_P(SpyThatPreventsSplittingWithApplicationFixture, SpyThatPreventsSplittingWithApplication) {
4698     SCOPED_FLAG_OVERRIDE(split_all_touches, false);
4699     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4700 
4701     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4702                                                                 ui::LogicalDisplayId::DEFAULT);
4703     spyWindow->setFrame(Rect(100, 100, 200, 200));
4704     spyWindow->setTrustedOverlay(true);
4705     spyWindow->setPreventSplitting(true);
4706     spyWindow->setSpy(true);
4707     // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4708     sp<FakeWindowHandle> inputSinkWindow =
4709             sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4710                                        ui::LogicalDisplayId::DEFAULT);
4711     inputSinkWindow->setFrame(Rect(100, 100, 200, 200)); // directly below the spy
4712     inputSinkWindow->setTrustedOverlay(true);
4713     inputSinkWindow->setPreventSplitting(GetParam());
4714     inputSinkWindow->setNoInputChannel(true);
4715 
4716     sp<FakeWindowHandle> appWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "App",
4717                                                                 ui::LogicalDisplayId::DEFAULT);
4718     appWindow->setFrame(Rect(0, 0, 100, 100));
4719 
4720     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4721     mDispatcher->onWindowInfosChanged(
4722             {{*spyWindow->getInfo(), *inputSinkWindow->getInfo(), *appWindow->getInfo()},
4723              {},
4724              0,
4725              0});
4726 
4727     // First finger lands outside of the appWindow, but inside of the spy window
4728     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4729                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4730                                       .build());
4731     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4732 
4733     mDispatcher->pilferPointers(spyWindow->getToken());
4734 
4735     // Second finger lands in the app, and goes to the spy window. It doesn't go to the app because
4736     // the spy is already pilfering the first pointer, and this automatically grants the remaining
4737     // new pointers to the spy, as well.
4738     mDispatcher->notifyMotion(
4739             MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4740                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4741                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4742                     .build());
4743 
4744     spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4745 
4746     // Now lift up the first pointer
4747     mDispatcher->notifyMotion(
4748             MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
4749                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4750                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4751                     .build());
4752     spyWindow->consumeMotionPointerUp(0, WithPointerCount(2));
4753 
4754     // And lift the remaining pointer!
4755     mDispatcher->notifyMotion(
4756             MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4757                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4758                     .build());
4759     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithPointerCount(1)));
4760 
4761     // Now send a new DOWN, which should again go to spy.
4762     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4763                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4764                                       .build());
4765     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4766     // The app window doesn't get any events this entire time because the spy received the events
4767     // first and pilfered, which makes all new pointers go to it as well.
4768     appWindow->assertNoEvents();
4769 }
4770 
4771 // Behaviour should be the same regardless of whether inputSink supports splitting.
4772 INSTANTIATE_TEST_SUITE_P(SpyThatPreventsSplittingWithApplication,
4773                          SpyThatPreventsSplittingWithApplicationFixture, testing::Bool());
4774 
TEST_F(InputDispatcherTest,HoverWithSpyWindows)4775 TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4776     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4777 
4778     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4779                                                                 ui::LogicalDisplayId::DEFAULT);
4780     spyWindow->setFrame(Rect(0, 0, 600, 800));
4781     spyWindow->setTrustedOverlay(true);
4782     spyWindow->setSpy(true);
4783     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4784                                                              ui::LogicalDisplayId::DEFAULT);
4785     window->setFrame(Rect(0, 0, 600, 800));
4786 
4787     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4788     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4789 
4790     // Send mouse cursor to the window
4791     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4792               injectMotionEvent(*mDispatcher,
4793                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4794                                                    AINPUT_SOURCE_MOUSE)
4795                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4796                                         .build()));
4797 
4798     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4799                                      WithSource(AINPUT_SOURCE_MOUSE)));
4800     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4801                                         WithSource(AINPUT_SOURCE_MOUSE)));
4802 
4803     window->assertNoEvents();
4804     spyWindow->assertNoEvents();
4805 }
4806 
TEST_F(InputDispatcherTest,MouseAndTouchWithSpyWindows_legacy)4807 TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4808     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
4809     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4810 
4811     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4812                                                                 ui::LogicalDisplayId::DEFAULT);
4813     spyWindow->setFrame(Rect(0, 0, 600, 800));
4814     spyWindow->setTrustedOverlay(true);
4815     spyWindow->setSpy(true);
4816     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4817                                                              ui::LogicalDisplayId::DEFAULT);
4818     window->setFrame(Rect(0, 0, 600, 800));
4819 
4820     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4821     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4822 
4823     // Send mouse cursor to the window
4824     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4825               injectMotionEvent(*mDispatcher,
4826                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4827                                                    AINPUT_SOURCE_MOUSE)
4828                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4829                                         .build()));
4830 
4831     // Move mouse cursor
4832     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4833               injectMotionEvent(*mDispatcher,
4834                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4835                                                    AINPUT_SOURCE_MOUSE)
4836                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4837                                         .build()));
4838 
4839     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4840                                      WithSource(AINPUT_SOURCE_MOUSE)));
4841     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4842                                         WithSource(AINPUT_SOURCE_MOUSE)));
4843     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4844                                      WithSource(AINPUT_SOURCE_MOUSE)));
4845     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4846                                         WithSource(AINPUT_SOURCE_MOUSE)));
4847     // Touch down on the window
4848     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4849               injectMotionEvent(*mDispatcher,
4850                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4851                                                    AINPUT_SOURCE_TOUCHSCREEN)
4852                                         .deviceId(SECOND_DEVICE_ID)
4853                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4854                                         .build()));
4855     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4856                                      WithSource(AINPUT_SOURCE_MOUSE)));
4857     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4858                                         WithSource(AINPUT_SOURCE_MOUSE)));
4859     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4860                                      WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4861     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4862                                         WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4863 
4864     // pilfer the motion, retaining the gesture on the spy window.
4865     EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4866     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4867                                      WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4868 
4869     // Touch UP on the window
4870     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4871               injectMotionEvent(*mDispatcher,
4872                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4873                                                    AINPUT_SOURCE_TOUCHSCREEN)
4874                                         .deviceId(SECOND_DEVICE_ID)
4875                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4876                                         .build()));
4877     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4878                                         WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4879 
4880     // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4881     // to send a new gesture. It should again go to both windows (spy and the window below), just
4882     // like the first gesture did, before pilfering. The window configuration has not changed.
4883 
4884     // One more tap - DOWN
4885     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4886               injectMotionEvent(*mDispatcher,
4887                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4888                                                    AINPUT_SOURCE_TOUCHSCREEN)
4889                                         .deviceId(SECOND_DEVICE_ID)
4890                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4891                                         .build()));
4892     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4893                                      WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4894     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4895                                         WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4896 
4897     // Touch UP on the window
4898     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4899               injectMotionEvent(*mDispatcher,
4900                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4901                                                    AINPUT_SOURCE_TOUCHSCREEN)
4902                                         .deviceId(SECOND_DEVICE_ID)
4903                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4904                                         .build()));
4905     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4906                                      WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4907     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4908                                         WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4909 
4910     window->assertNoEvents();
4911     spyWindow->assertNoEvents();
4912 }
4913 
TEST_F(InputDispatcherTest,MouseAndTouchWithSpyWindows)4914 TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4915     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4916     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4917 
4918     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4919                                                                 ui::LogicalDisplayId::DEFAULT);
4920     spyWindow->setFrame(Rect(0, 0, 600, 800));
4921     spyWindow->setTrustedOverlay(true);
4922     spyWindow->setSpy(true);
4923     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4924                                                              ui::LogicalDisplayId::DEFAULT);
4925     window->setFrame(Rect(0, 0, 600, 800));
4926 
4927     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4928     mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4929 
4930     // Send mouse cursor to the window
4931     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4932                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4933                                       .build());
4934 
4935     // Move mouse cursor
4936     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4937                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4938                                       .build());
4939 
4940     window->consumeMotionEvent(
4941             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4942     spyWindow->consumeMotionEvent(
4943             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4944     window->consumeMotionEvent(
4945             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4946     spyWindow->consumeMotionEvent(
4947             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4948     // Touch down on the window
4949     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4950                                       .deviceId(SECOND_DEVICE_ID)
4951                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4952                                       .build());
4953     window->consumeMotionEvent(
4954             AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4955     spyWindow->consumeMotionEvent(
4956             AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4957 
4958     // pilfer the motion, retaining the gesture on the spy window.
4959     EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4960     window->consumeMotionEvent(
4961             AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4962     // Mouse hover is not pilfered
4963 
4964     // Touch UP on the window
4965     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4966                                       .deviceId(SECOND_DEVICE_ID)
4967                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4968                                       .build());
4969     spyWindow->consumeMotionEvent(
4970             AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4971 
4972     // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4973     // to send a new gesture. It should again go to both windows (spy and the window below), just
4974     // like the first gesture did, before pilfering. The window configuration has not changed.
4975 
4976     // One more tap - DOWN
4977     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4978                                       .deviceId(SECOND_DEVICE_ID)
4979                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4980                                       .build());
4981     window->consumeMotionEvent(
4982             AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4983     spyWindow->consumeMotionEvent(
4984             AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4985 
4986     // Touch UP on the window
4987     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4988                                       .deviceId(SECOND_DEVICE_ID)
4989                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4990                                       .build());
4991     window->consumeMotionEvent(
4992             AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4993     spyWindow->consumeMotionEvent(
4994             AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4995 
4996     // Mouse movement continues normally as well
4997     // Move mouse cursor
4998     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4999                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
5000                                       .build());
5001     window->consumeMotionEvent(
5002             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
5003     spyWindow->consumeMotionEvent(
5004             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
5005 
5006     window->assertNoEvents();
5007     spyWindow->assertNoEvents();
5008 }
5009 
5010 // This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
5011 // directly in this test.
TEST_F(InputDispatcherTest,HoverEnterMouseClickAndHoverExit)5012 TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
5013     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5014     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5015                                                              ui::LogicalDisplayId::DEFAULT);
5016     window->setFrame(Rect(0, 0, 1200, 800));
5017 
5018     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
5019 
5020     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5021 
5022     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5023               injectMotionEvent(*mDispatcher,
5024                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
5025                                                    AINPUT_SOURCE_MOUSE)
5026                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5027                                         .build()));
5028     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5029     // Inject a series of mouse events for a mouse click
5030     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5031               injectMotionEvent(*mDispatcher,
5032                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5033                                         .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
5034                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5035                                         .build()));
5036     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5037     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5038 
5039     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5040               injectMotionEvent(*mDispatcher,
5041                                 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
5042                                                    AINPUT_SOURCE_MOUSE)
5043                                         .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
5044                                         .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
5045                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5046                                         .build()));
5047     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
5048 
5049     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5050               injectMotionEvent(*mDispatcher,
5051                                 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
5052                                                    AINPUT_SOURCE_MOUSE)
5053                                         .buttonState(0)
5054                                         .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
5055                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5056                                         .build()));
5057     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
5058 
5059     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5060               injectMotionEvent(*mDispatcher,
5061                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
5062                                         .buttonState(0)
5063                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5064                                         .build()));
5065     window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
5066 
5067     // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
5068     // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
5069     ASSERT_EQ(InputEventInjectionResult::FAILED,
5070               injectMotionEvent(*mDispatcher,
5071                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
5072                                                    AINPUT_SOURCE_MOUSE)
5073                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5074                                         .build()));
5075     window->assertNoEvents();
5076 }
5077 
5078 /**
5079  * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
5080  * is generated.
5081  */
TEST_F(InputDispatcherTest,HoverExitIsSentToRemovedWindow)5082 TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
5083     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5084     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5085                                                              ui::LogicalDisplayId::DEFAULT);
5086     window->setFrame(Rect(0, 0, 1200, 800));
5087 
5088     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
5089 
5090     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5091 
5092     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5093               injectMotionEvent(*mDispatcher,
5094                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
5095                                                    AINPUT_SOURCE_MOUSE)
5096                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5097                                         .build()));
5098     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5099 
5100     // Remove the window, but keep the channel.
5101     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
5102     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
5103 }
5104 
5105 /**
5106  * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
5107  */
TEST_F(InputDispatcherTest,InvalidA11yHoverStreamDoesNotCrash)5108 TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
5109     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5110     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5111                                                              ui::LogicalDisplayId::DEFAULT);
5112     window->setFrame(Rect(0, 0, 1200, 800));
5113 
5114     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
5115 
5116     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5117 
5118     MotionEventBuilder hoverEnterBuilder =
5119             MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5120                     .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5121                     .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5122     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5123               injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5124     window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5125     // Another HOVER_ENTER would be inconsistent, and should therefore fail to
5126     // get injected.
5127     ASSERT_EQ(InputEventInjectionResult::FAILED,
5128               injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5129 }
5130 
5131 /**
5132  * Invalid events injected by input filter are rejected.
5133  */
TEST_F(InputDispatcherTest,InvalidA11yEventsGetRejected)5134 TEST_F(InputDispatcherTest, InvalidA11yEventsGetRejected) {
5135     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5136     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5137                                                              ui::LogicalDisplayId::DEFAULT);
5138 
5139     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
5140 
5141     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5142 
5143     // a11y sets 'POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY' policy flag during injection, so define
5144     // a custom injection function here for convenience.
5145     auto injectFromAccessibility = [&](int32_t action, float x, float y) {
5146         MotionEvent event = MotionEventBuilder(action, AINPUT_SOURCE_TOUCHSCREEN)
5147                                     .pointer(PointerBuilder(0, ToolType::FINGER).x(x).y(y))
5148                                     .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT)
5149                                     .build();
5150         return injectMotionEvent(*mDispatcher, event, 100ms,
5151                                  InputEventInjectionSync::WAIT_FOR_RESULT, /*targetUid=*/{},
5152                                  POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_FILTERED |
5153                                          POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY);
5154     };
5155 
5156     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5157               injectFromAccessibility(ACTION_DOWN, /*x=*/300, /*y=*/400));
5158     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5159               injectFromAccessibility(ACTION_MOVE, /*x=*/310, /*y=*/420));
5160     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5161     window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5162     // finger is still down, so a new DOWN event should be rejected!
5163     ASSERT_EQ(InputEventInjectionResult::FAILED,
5164               injectFromAccessibility(ACTION_DOWN, /*x=*/340, /*y=*/410));
5165 
5166     // if the gesture is correctly finished, new down event will succeed
5167     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5168               injectFromAccessibility(ACTION_MOVE, /*x=*/320, /*y=*/430));
5169     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5170               injectFromAccessibility(ACTION_UP, /*x=*/320, /*y=*/430));
5171     window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5172     window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5173 
5174     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5175               injectFromAccessibility(ACTION_DOWN, /*x=*/350, /*y=*/460));
5176     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5177 }
5178 
5179 /**
5180  * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
5181  */
TEST_F(InputDispatcherTest,TouchDownAfterMouseHover_legacy)5182 TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
5183     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
5184     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5185     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5186                                                              ui::LogicalDisplayId::DEFAULT);
5187     window->setFrame(Rect(0, 0, 100, 100));
5188 
5189     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5190 
5191     const int32_t mouseDeviceId = 7;
5192     const int32_t touchDeviceId = 4;
5193 
5194     // Start hovering with the mouse
5195     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5196                                       .deviceId(mouseDeviceId)
5197                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5198                                       .build());
5199     window->consumeMotionEvent(
5200             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5201 
5202     // Touch goes down
5203     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5204                                       .deviceId(touchDeviceId)
5205                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5206                                       .build());
5207 
5208     window->consumeMotionEvent(
5209             AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
5210     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5211 }
5212 
5213 /**
5214  * If mouse is hovering when the touch goes down, the hovering should not be stopped.
5215  */
TEST_F(InputDispatcherTest,TouchDownAfterMouseHover)5216 TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
5217     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5218     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5219     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5220                                                              ui::LogicalDisplayId::DEFAULT);
5221     window->setFrame(Rect(0, 0, 100, 100));
5222 
5223     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5224 
5225     const int32_t mouseDeviceId = 7;
5226     const int32_t touchDeviceId = 4;
5227 
5228     // Start hovering with the mouse
5229     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5230                                       .deviceId(mouseDeviceId)
5231                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5232                                       .build());
5233     window->consumeMotionEvent(
5234             AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5235 
5236     // Touch goes down
5237     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5238                                       .deviceId(touchDeviceId)
5239                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5240                                       .build());
5241     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5242 }
5243 
5244 /**
5245  * Inject a mouse hover event followed by a tap from touchscreen.
5246  * The tap causes a HOVER_EXIT event to be generated because the current event
5247  * stream's source has been switched.
5248  */
TEST_F(InputDispatcherTest,MouseHoverAndTouchTap_legacy)5249 TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
5250     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
5251     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5252     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5253                                                              ui::LogicalDisplayId::DEFAULT);
5254     window->setFrame(Rect(0, 0, 100, 100));
5255 
5256     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5257     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5258                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5259                                       .build());
5260     ASSERT_NO_FATAL_FAILURE(
5261             window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5262                                              WithSource(AINPUT_SOURCE_MOUSE))));
5263 
5264     // Tap on the window
5265     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5266                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5267                                       .build());
5268     ASSERT_NO_FATAL_FAILURE(
5269             window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5270                                              WithSource(AINPUT_SOURCE_MOUSE))));
5271 
5272     ASSERT_NO_FATAL_FAILURE(
5273             window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5274                                              WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5275 
5276     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5277                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5278                                       .build());
5279     ASSERT_NO_FATAL_FAILURE(
5280             window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5281                                              WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5282 }
5283 
5284 /**
5285  * Send a mouse hover event followed by a tap from touchscreen.
5286  * The tap causes a HOVER_EXIT event to be generated because the current event
5287  * stream's source has been switched.
5288  */
TEST_F(InputDispatcherTest,MouseHoverAndTouchTap)5289 TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
5290     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5291     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5292     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5293                                                              ui::LogicalDisplayId::DEFAULT);
5294     window->setFrame(Rect(0, 0, 100, 100));
5295 
5296     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5297     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5298                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5299                                       .build());
5300 
5301     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5302                                      WithSource(AINPUT_SOURCE_MOUSE)));
5303 
5304     // Tap on the window
5305     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5306                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5307                                       .build());
5308 
5309     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5310                                      WithSource(AINPUT_SOURCE_MOUSE)));
5311 
5312     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5313                                      WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5314 
5315     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5316                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5317                                       .build());
5318 
5319     window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5320                                      WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5321 }
5322 
TEST_F(InputDispatcherTest,HoverEnterMoveRemoveWindowsInSecondDisplay)5323 TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
5324     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5325     sp<FakeWindowHandle> windowDefaultDisplay =
5326             sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
5327                                        ui::LogicalDisplayId::DEFAULT);
5328     windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
5329     sp<FakeWindowHandle> windowSecondDisplay =
5330             sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
5331                                        SECOND_DISPLAY_ID);
5332     windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
5333 
5334     mDispatcher->onWindowInfosChanged(
5335             {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
5336 
5337     // Set cursor position in window in default display and check that hover enter and move
5338     // events are generated.
5339     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5340               injectMotionEvent(*mDispatcher,
5341                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5342                                                    AINPUT_SOURCE_MOUSE)
5343                                         .displayId(ui::LogicalDisplayId::DEFAULT)
5344                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
5345                                         .build()));
5346     windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5347 
5348     // Remove all windows in secondary display and check that no event happens on window in
5349     // primary display.
5350     mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
5351 
5352     windowDefaultDisplay->assertNoEvents();
5353 
5354     // Move cursor position in window in default display and check that only hover move
5355     // event is generated and not hover enter event.
5356     mDispatcher->onWindowInfosChanged(
5357             {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
5358     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5359               injectMotionEvent(*mDispatcher,
5360                                 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5361                                                    AINPUT_SOURCE_MOUSE)
5362                                         .displayId(ui::LogicalDisplayId::DEFAULT)
5363                                         .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
5364                                         .build()));
5365     windowDefaultDisplay->consumeMotionEvent(
5366             AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
5367                   WithSource(AINPUT_SOURCE_MOUSE)));
5368     windowDefaultDisplay->assertNoEvents();
5369 }
5370 
TEST_F(InputDispatcherTest,DispatchMouseEventsUnderCursor)5371 TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
5372     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5373 
5374     sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
5375                                                                  ui::LogicalDisplayId::DEFAULT);
5376     windowLeft->setFrame(Rect(0, 0, 600, 800));
5377     sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
5378                                                                   ui::LogicalDisplayId::DEFAULT);
5379     windowRight->setFrame(Rect(600, 0, 1200, 800));
5380 
5381     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
5382 
5383     mDispatcher->onWindowInfosChanged(
5384             {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
5385 
5386     // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
5387     // left window. This event should be dispatched to the left window.
5388     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5389               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
5390                                 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
5391     windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
5392     windowRight->assertNoEvents();
5393 }
5394 
TEST_F(InputDispatcherTest,NotifyDeviceReset_CancelsKeyStream)5395 TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
5396     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5397     sp<FakeWindowHandle> window =
5398             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5399                                        ui::LogicalDisplayId::DEFAULT);
5400     window->setFocusable(true);
5401 
5402     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5403     setFocusedWindow(window);
5404 
5405     window->consumeFocusEvent(true);
5406 
5407     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5408 
5409     // Window should receive key down event.
5410     window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5411 
5412     // When device reset happens, that key stream should be terminated with FLAG_CANCELED
5413     // on the app side.
5414     mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5415     window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
5416 }
5417 
TEST_F(InputDispatcherTest,NotifyDeviceReset_CancelsMotionStream)5418 TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
5419     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5420     sp<FakeWindowHandle> window =
5421             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5422                                        ui::LogicalDisplayId::DEFAULT);
5423 
5424     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5425 
5426     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5427                                                  AINPUT_SOURCE_TOUCHSCREEN,
5428                                                  ui::LogicalDisplayId::DEFAULT));
5429 
5430     // Window should receive motion down event.
5431     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
5432 
5433     // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
5434     // on the app side.
5435     mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5436     window->consumeMotionEvent(
5437             AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
5438 }
5439 
TEST_F(InputDispatcherTest,NotifyDeviceResetCancelsHoveringStream)5440 TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
5441     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5442     sp<FakeWindowHandle> window =
5443             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5444                                        ui::LogicalDisplayId::DEFAULT);
5445 
5446     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5447 
5448     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5449                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5450                                       .build());
5451 
5452     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5453 
5454     // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5455     mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5456     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5457 
5458     // After the device has been reset, a new hovering stream can be sent to the window
5459     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5460                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5461                                       .build());
5462     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5463 }
5464 
TEST_F(InputDispatcherTest,InterceptKeyByPolicy)5465 TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5466     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5467     sp<FakeWindowHandle> window =
5468             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5469                                        ui::LogicalDisplayId::DEFAULT);
5470     window->setFocusable(true);
5471 
5472     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5473     setFocusedWindow(window);
5474 
5475     window->consumeFocusEvent(true);
5476 
5477     const NotifyKeyArgs keyArgs =
5478             generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5479     const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5480     const nsecs_t injectTime = keyArgs.eventTime;
5481     mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
5482     mDispatcher->notifyKey(keyArgs);
5483     // The dispatching time should be always greater than or equal to intercept key timeout.
5484     window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5485     ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5486                 std::chrono::nanoseconds(interceptKeyTimeout).count());
5487 }
5488 
5489 /**
5490  * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5491  */
TEST_F(InputDispatcherTest,InterceptKeyIfKeyUp)5492 TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5493     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5494     sp<FakeWindowHandle> window =
5495             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5496                                        ui::LogicalDisplayId::DEFAULT);
5497     window->setFocusable(true);
5498 
5499     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5500     setFocusedWindow(window);
5501 
5502     window->consumeFocusEvent(true);
5503 
5504     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5505     window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5506 
5507     // Set a value that's significantly larger than the default consumption timeout. If the
5508     // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5509     mFakePolicy->setInterceptKeyTimeout(600ms);
5510     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
5511     // Window should receive key event immediately when same key up.
5512     window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
5513 }
5514 
5515 /**
5516  * Two windows. First is a regular window. Second does not overlap with the first, and has
5517  * WATCH_OUTSIDE_TOUCH.
5518  * Both windows are owned by the same UID.
5519  * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5520  * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5521  */
TEST_F(InputDispatcherTest,ActionOutsideForOwnedWindowHasValidCoordinates)5522 TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5523     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5524     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5525                                                              ui::LogicalDisplayId::DEFAULT);
5526     window->setFrame(Rect{0, 0, 100, 100});
5527 
5528     sp<FakeWindowHandle> outsideWindow =
5529             sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
5530                                        ui::LogicalDisplayId::DEFAULT);
5531     outsideWindow->setFrame(Rect{100, 100, 200, 200});
5532     outsideWindow->setWatchOutsideTouch(true);
5533     // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
5534     mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
5535 
5536     // Tap on first window.
5537     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5538                                                  AINPUT_SOURCE_TOUCHSCREEN,
5539                                                  ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
5540     window->consumeMotionDown();
5541     // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5542     // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5543     outsideWindow->consumeMotionEvent(
5544             AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
5545 
5546     // Ensure outsideWindow doesn't get any more events for the gesture.
5547     mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5548                                                  ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
5549     window->consumeMotionMove();
5550     outsideWindow->assertNoEvents();
5551 }
5552 
5553 /**
5554  * Three windows:
5555  * - Left window
5556  * - Right window
5557  * - Outside window(watch for ACTION_OUTSIDE events)
5558  * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5559  * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5560  * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5561  *
5562  * First, device A report a down event landed in the right window, the outside window can receive
5563  * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5564  * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5565  * coordinates, after these, device A and device B continue report MOVE event, the right and left
5566  * window can receive it, but outside window event can't receive it.
5567  */
TEST_F(InputDispatcherTest,ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice)5568 TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5569     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5570     sp<FakeWindowHandle> leftWindow =
5571             sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
5572                                        ui::LogicalDisplayId::DEFAULT);
5573     leftWindow->setFrame(Rect{0, 0, 100, 100});
5574     leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5575 
5576     sp<FakeWindowHandle> outsideWindow =
5577             sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
5578                                        ui::LogicalDisplayId::DEFAULT);
5579     outsideWindow->setFrame(Rect{100, 100, 200, 200});
5580     outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5581     outsideWindow->setWatchOutsideTouch(true);
5582 
5583     std::shared_ptr<FakeApplicationHandle> anotherApplication =
5584             std::make_shared<FakeApplicationHandle>();
5585     sp<FakeWindowHandle> rightWindow =
5586             sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
5587                                        ui::LogicalDisplayId::DEFAULT);
5588     rightWindow->setFrame(Rect{100, 0, 200, 100});
5589     rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5590 
5591     // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5592     // when left window or right window is tapped
5593     mDispatcher->onWindowInfosChanged(
5594             {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5595              {},
5596              0,
5597              0});
5598 
5599     const DeviceId deviceA = 9;
5600     const DeviceId deviceB = 3;
5601 
5602     // Tap on right window use device A
5603     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5604                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5605                                       .deviceId(deviceA)
5606                                       .build());
5607     leftWindow->assertNoEvents();
5608     rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5609     // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5610     // with zeroed coords.
5611     outsideWindow->consumeMotionEvent(
5612             AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5613 
5614     // Tap on left window use device B
5615     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5616                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5617                                       .deviceId(deviceB)
5618                                       .build());
5619     leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5620     rightWindow->assertNoEvents();
5621     // Because new gesture down on the left window that has the same owner with outside Window, the
5622     // outside Window should receive the ACTION_OUTSIDE with coords.
5623     outsideWindow->consumeMotionEvent(
5624             AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5625 
5626     // Ensure that windows that can only accept outside do not receive remaining gestures
5627     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5628                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5629                                       .deviceId(deviceA)
5630                                       .build());
5631     leftWindow->assertNoEvents();
5632     rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5633 
5634     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5635                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5636                                       .deviceId(deviceB)
5637                                       .build());
5638     leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5639     rightWindow->assertNoEvents();
5640     outsideWindow->assertNoEvents();
5641 }
5642 
5643 /**
5644  * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5645  * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5646  * ACTION_OUTSIDE event is sent per gesture.
5647  */
TEST_F(InputDispatcherTest,ActionOutsideSentOnlyWhenAWindowIsTouched)5648 TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5649     // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5650     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5651     sp<FakeWindowHandle> window =
5652             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5653                                        ui::LogicalDisplayId::DEFAULT);
5654     window->setWatchOutsideTouch(true);
5655     window->setFrame(Rect{0, 0, 100, 100});
5656     sp<FakeWindowHandle> secondWindow =
5657             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5658                                        ui::LogicalDisplayId::DEFAULT);
5659     secondWindow->setFrame(Rect{100, 100, 200, 200});
5660     sp<FakeWindowHandle> thirdWindow =
5661             sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
5662                                        ui::LogicalDisplayId::DEFAULT);
5663     thirdWindow->setFrame(Rect{200, 200, 300, 300});
5664     mDispatcher->onWindowInfosChanged(
5665             {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
5666 
5667     // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
5668     mDispatcher->notifyMotion(
5669             generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5670                                ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
5671     window->assertNoEvents();
5672     secondWindow->assertNoEvents();
5673 
5674     // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5675     // Now, `window` should get ACTION_OUTSIDE.
5676     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5677                                                  ui::LogicalDisplayId::DEFAULT,
5678                                                  {PointF{-10, -10}, PointF{105, 105}}));
5679     const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5680     window->consumeMotionEvent(
5681             AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
5682     secondWindow->consumeMotionDown();
5683     thirdWindow->assertNoEvents();
5684 
5685     // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5686     // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
5687     mDispatcher->notifyMotion(
5688             generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5689                                ui::LogicalDisplayId::DEFAULT,
5690                                {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
5691     window->assertNoEvents();
5692     secondWindow->consumeMotionMove();
5693     thirdWindow->consumeMotionDown();
5694 }
5695 
TEST_F(InputDispatcherTest,OnWindowInfosChanged_RemoveAllWindowsOnDisplay)5696 TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5697     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5698     sp<FakeWindowHandle> window =
5699             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5700                                        ui::LogicalDisplayId::DEFAULT);
5701     window->setFocusable(true);
5702 
5703     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5704     setFocusedWindow(window);
5705 
5706     window->consumeFocusEvent(true);
5707 
5708     const NotifyKeyArgs keyDown =
5709             generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5710     const NotifyKeyArgs keyUp =
5711             generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
5712     mDispatcher->notifyKey(keyDown);
5713     mDispatcher->notifyKey(keyUp);
5714 
5715     window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5716     window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
5717 
5718     // All windows are removed from the display. Ensure that we can no longer dispatch to it.
5719     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
5720 
5721     window->consumeFocusEvent(false);
5722 
5723     mDispatcher->notifyKey(keyDown);
5724     mDispatcher->notifyKey(keyUp);
5725     window->assertNoEvents();
5726 }
5727 
TEST_F(InputDispatcherTest,NonSplitTouchableWindowReceivesMultiTouch)5728 TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
5729     SCOPED_FLAG_OVERRIDE(split_all_touches, false);
5730     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5731     sp<FakeWindowHandle> window =
5732             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5733                                        ui::LogicalDisplayId::DEFAULT);
5734     // Ensure window is non-split and have some transform.
5735     window->setPreventSplitting(true);
5736     window->setWindowOffset(20, 40);
5737     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5738 
5739     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5740               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5741                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
5742             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5743     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
5744 
5745     const MotionEvent secondFingerDownEvent =
5746             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5747                     .displayId(ui::LogicalDisplayId::DEFAULT)
5748                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
5749                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5750                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
5751                     .build();
5752     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5753               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
5754                                 InputEventInjectionSync::WAIT_FOR_RESULT))
5755             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5756 
5757     std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5758     ASSERT_NE(nullptr, event);
5759     EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5760     EXPECT_EQ(70, event->getX(0));  // 50 + 20
5761     EXPECT_EQ(90, event->getY(0));  // 50 + 40
5762     EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5763     EXPECT_EQ(-10, event->getY(1)); // -50 + 40
5764 }
5765 
5766 /**
5767  * Two windows: a splittable and a non-splittable.
5768  * The non-splittable window shouldn't receive any "incomplete" gestures.
5769  * Send the first pointer to the splittable window, and then touch the non-splittable window.
5770  * The second pointer should be dropped because the initial window is splittable, so it won't get
5771  * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5772  * "incomplete" gestures.
5773  */
TEST_F(InputDispatcherTest,SplittableAndNonSplittableWindows)5774 TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
5775     SCOPED_FLAG_OVERRIDE(split_all_touches, false);
5776     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5777     sp<FakeWindowHandle> leftWindow =
5778             sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
5779                                        ui::LogicalDisplayId::DEFAULT);
5780     leftWindow->setPreventSplitting(false);
5781     leftWindow->setFrame(Rect(0, 0, 100, 100));
5782     sp<FakeWindowHandle> rightWindow =
5783             sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
5784                                        ui::LogicalDisplayId::DEFAULT);
5785     rightWindow->setPreventSplitting(true);
5786     rightWindow->setFrame(Rect(100, 100, 200, 200));
5787     mDispatcher->onWindowInfosChanged(
5788             {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5789 
5790     // Touch down on left, splittable window
5791     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5792                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5793                                       .build());
5794     leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5795 
5796     mDispatcher->notifyMotion(
5797             MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5798                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5799                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5800                     .build());
5801     leftWindow->assertNoEvents();
5802     rightWindow->assertNoEvents();
5803 }
5804 
5805 /**
5806  * Three windows:
5807  * 1) A window on the left, with flag dup_to_wallpaper
5808  * 2) A window on the right, with flag slippery
5809  * 3) A wallpaper window  under the left window
5810  * When touch slips from right window to left, the wallpaper should receive a similar slippery
5811  * enter event. Later on, when another device becomes active, the wallpaper should receive
5812  * consistent streams from the new device, and also from the old device.
5813  * This test attempts to reproduce a crash in the dispatcher where the wallpaper target's downTime
5814  * was not getting set during slippery entrance.
5815  */
TEST_F(InputDispatcherTest,WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch)5816 TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch) {
5817     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5818     std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
5819     std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
5820     std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
5821     sp<FakeWindowHandle> wallpaper =
5822             sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
5823                                        ui::LogicalDisplayId::DEFAULT);
5824     wallpaper->setIsWallpaper(true);
5825     wallpaper->setPreventSplitting(true);
5826     wallpaper->setTouchable(false);
5827 
5828     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
5829                                                                  ui::LogicalDisplayId::DEFAULT);
5830     leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
5831     leftWindow->setDupTouchToWallpaper(true);
5832 
5833     sp<FakeWindowHandle> rightWindow =
5834             sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
5835                                        ui::LogicalDisplayId::DEFAULT);
5836     rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
5837     rightWindow->setSlippery(true);
5838     rightWindow->setWatchOutsideTouch(true);
5839     rightWindow->setTrustedOverlay(true);
5840 
5841     mDispatcher->onWindowInfosChanged(
5842             {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
5843 
5844     const DeviceId deviceA = 3;
5845     const DeviceId deviceB = 9;
5846 
5847     // First finger from device A into right window
5848     NotifyMotionArgs deviceADownArgs =
5849             MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5850                     .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5851                     .deviceId(deviceA)
5852                     .build();
5853 
5854     mDispatcher->notifyMotion(deviceADownArgs);
5855     rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5856 
5857     // Move the finger of device A from right window into left window. It should slip.
5858     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5859                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
5860                                       .deviceId(deviceA)
5861                                       .downTime(deviceADownArgs.downTime)
5862                                       .build());
5863 
5864     leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5865     rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
5866     wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5867 
5868     // Finger from device B down into left window
5869     NotifyMotionArgs deviceBDownArgs =
5870             MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5871                     .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5872                     .deviceId(deviceB)
5873                     .build();
5874     mDispatcher->notifyMotion(deviceBDownArgs);
5875     leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5876     wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5877 
5878     rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
5879 
5880     // Move finger from device B, still keeping it in the left window
5881     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5882                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5883                                       .deviceId(deviceB)
5884                                       .downTime(deviceBDownArgs.downTime)
5885                                       .build());
5886     leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5887     wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5888 
5889     // Lift the finger from device B
5890     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5891                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5892                                       .deviceId(deviceB)
5893                                       .downTime(deviceBDownArgs.downTime)
5894                                       .build());
5895     leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5896     wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5897 
5898     // Move the finger of device A, keeping it in the left window
5899     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5900                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5901                                       .deviceId(deviceA)
5902                                       .downTime(deviceADownArgs.downTime)
5903                                       .build());
5904 
5905     leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
5906     wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
5907 
5908     // Second finger down from device A, into the right window. It should be split into:
5909     // MOVE for the left window (due to existing implementation) + a DOWN into the right window
5910     // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
5911     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5912                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5913                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5914                                       .deviceId(deviceA)
5915                                       .downTime(deviceADownArgs.downTime)
5916                                       .build());
5917     auto firstFingerMoveFromDeviceA = AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE),
5918                                             WithPointerCount(1), WithPointerId(0, 0));
5919     leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
5920     wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
5921     rightWindow->consumeMotionEvent(
5922             AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
5923 
5924     // Lift up the second finger.
5925     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5926                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5927                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5928                                       .deviceId(deviceA)
5929                                       .downTime(deviceADownArgs.downTime)
5930                                       .build());
5931 
5932     rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5933     leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
5934     wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
5935 
5936     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5937                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5938                                       .deviceId(deviceA)
5939                                       .downTime(deviceADownArgs.downTime)
5940                                       .build());
5941 
5942     leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5943     wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5944     rightWindow->assertNoEvents();
5945 }
5946 
5947 /**
5948  * Same test as above, but with enable_multi_device_same_window_stream flag set to false.
5949  */
TEST_F(InputDispatcherTest,WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch_legacy)5950 TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch_legacy) {
5951     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
5952     std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
5953     std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
5954     std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
5955     sp<FakeWindowHandle> wallpaper =
5956             sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
5957                                        ui::LogicalDisplayId::DEFAULT);
5958     wallpaper->setIsWallpaper(true);
5959     wallpaper->setPreventSplitting(true);
5960     wallpaper->setTouchable(false);
5961 
5962     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
5963                                                                  ui::LogicalDisplayId::DEFAULT);
5964     leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
5965     leftWindow->setDupTouchToWallpaper(true);
5966 
5967     sp<FakeWindowHandle> rightWindow =
5968             sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
5969                                        ui::LogicalDisplayId::DEFAULT);
5970     rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
5971     rightWindow->setSlippery(true);
5972     rightWindow->setWatchOutsideTouch(true);
5973     rightWindow->setTrustedOverlay(true);
5974 
5975     mDispatcher->onWindowInfosChanged(
5976             {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
5977 
5978     const DeviceId deviceA = 3;
5979     const DeviceId deviceB = 9;
5980 
5981     // First finger from device A into right window
5982     NotifyMotionArgs deviceADownArgs =
5983             MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5984                     .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5985                     .deviceId(deviceA)
5986                     .build();
5987 
5988     mDispatcher->notifyMotion(deviceADownArgs);
5989     rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5990 
5991     // Move the finger of device A from right window into left window. It should slip.
5992     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5993                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
5994                                       .deviceId(deviceA)
5995                                       .downTime(deviceADownArgs.downTime)
5996                                       .build());
5997 
5998     leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5999     rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6000     wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6001 
6002     // Finger from device B down into left window
6003     NotifyMotionArgs deviceBDownArgs =
6004             MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6005                     .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
6006                     .deviceId(deviceB)
6007                     .build();
6008     mDispatcher->notifyMotion(deviceBDownArgs);
6009     leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
6010     leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
6011     wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
6012     wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
6013 
6014     rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
6015 
6016     // Move finger from device B, still keeping it in the left window
6017     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6018                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
6019                                       .deviceId(deviceB)
6020                                       .downTime(deviceBDownArgs.downTime)
6021                                       .build());
6022     leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
6023     wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
6024 
6025     // Lift the finger from device B
6026     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6027                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
6028                                       .deviceId(deviceB)
6029                                       .downTime(deviceBDownArgs.downTime)
6030                                       .build());
6031     leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
6032     wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
6033 
6034     // Move the finger of device A, keeping it in the left window
6035     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6036                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6037                                       .deviceId(deviceA)
6038                                       .downTime(deviceADownArgs.downTime)
6039                                       .build());
6040     // This device was already canceled, so MOVE events will not be arriving to the windows from it.
6041 
6042     // Second finger down from device A, into the right window. It should be split into:
6043     // MOVE for the left window (due to existing implementation) + a DOWN into the right window
6044     // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
6045     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6046                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6047                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
6048                                       .deviceId(deviceA)
6049                                       .downTime(deviceADownArgs.downTime)
6050                                       .build());
6051     rightWindow->consumeMotionEvent(
6052             AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
6053 
6054     // Lift up the second finger.
6055     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6056                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6057                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
6058                                       .deviceId(deviceA)
6059                                       .downTime(deviceADownArgs.downTime)
6060                                       .build());
6061 
6062     rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
6063 
6064     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6065                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6066                                       .deviceId(deviceA)
6067                                       .downTime(deviceADownArgs.downTime)
6068                                       .build());
6069     rightWindow->assertNoEvents();
6070 }
6071 
6072 /**
6073  * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
6074  * down event to the right window. Device B sends a down event to the left window, and then a
6075  * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
6076  * POINTER_DOWN event should only go to the left window, and not to the right window.
6077  * This test attempts to reproduce a crash.
6078  */
TEST_F(InputDispatcherTest,MultiDeviceTwoWindowsPreventSplitting)6079 TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
6080     SCOPED_FLAG_OVERRIDE(split_all_touches, false);
6081     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6082     sp<FakeWindowHandle> leftWindow =
6083             sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
6084                                        ui::LogicalDisplayId::DEFAULT);
6085     leftWindow->setFrame(Rect(0, 0, 100, 100));
6086     leftWindow->setPreventSplitting(true);
6087 
6088     sp<FakeWindowHandle> rightWindow =
6089             sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
6090                                        ui::LogicalDisplayId::DEFAULT);
6091     rightWindow->setFrame(Rect(100, 0, 200, 100));
6092 
6093     mDispatcher->onWindowInfosChanged(
6094             {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
6095 
6096     const DeviceId deviceA = 9;
6097     const DeviceId deviceB = 3;
6098     // Touch the right window with device A
6099     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6100                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6101                                       .deviceId(deviceA)
6102                                       .build());
6103     rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
6104     // Touch the left window with device B
6105     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6106                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6107                                       .deviceId(deviceB)
6108                                       .build());
6109     leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
6110     // Send a second pointer from device B to the right window. It shouldn't go to the right window
6111     // because the left window prevents splitting.
6112     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6113                                       .deviceId(deviceB)
6114                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6115                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6116                                       .build());
6117     leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
6118 
6119     // Finish the gesture for both devices
6120     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6121                                       .deviceId(deviceB)
6122                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6123                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6124                                       .build());
6125     leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
6126     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6127                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6128                                       .deviceId(deviceB)
6129                                       .build());
6130     leftWindow->consumeMotionEvent(
6131             AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
6132     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6133                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6134                                       .deviceId(deviceA)
6135                                       .build());
6136     rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
6137 }
6138 
TEST_F(InputDispatcherTest,TouchpadThreeFingerSwipeOnlySentToTrustedOverlays)6139 TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
6140     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6141     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6142                                                              ui::LogicalDisplayId::DEFAULT);
6143     window->setFrame(Rect(0, 0, 400, 400));
6144     sp<FakeWindowHandle> trustedOverlay =
6145             sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
6146                                        ui::LogicalDisplayId::DEFAULT);
6147     trustedOverlay->setSpy(true);
6148     trustedOverlay->setTrustedOverlay(true);
6149 
6150     mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
6151 
6152     // Start a three-finger touchpad swipe
6153     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6154                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6155                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6156                                       .build());
6157     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
6158                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6159                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6160                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6161                                       .build());
6162     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
6163                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6164                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6165                                       .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
6166                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6167                                       .build());
6168 
6169     trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6170     trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
6171     trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
6172 
6173     // Move the swipe a bit
6174     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6175                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6176                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6177                                       .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6178                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6179                                       .build());
6180 
6181     trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6182 
6183     // End the swipe
6184     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
6185                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6186                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6187                                       .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6188                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6189                                       .build());
6190     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
6191                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6192                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6193                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6194                                       .build());
6195     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
6196                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6197                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6198                                       .build());
6199 
6200     trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
6201     trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
6202     trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
6203 
6204     window->assertNoEvents();
6205 }
6206 
TEST_F(InputDispatcherTest,TouchpadThreeFingerSwipeNotSentToSingleWindow)6207 TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
6208     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6209     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6210                                                              ui::LogicalDisplayId::DEFAULT);
6211     window->setFrame(Rect(0, 0, 400, 400));
6212     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6213 
6214     // Start a three-finger touchpad swipe
6215     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6216                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6217                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6218                                       .build());
6219     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
6220                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6221                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6222                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6223                                       .build());
6224     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
6225                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6226                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6227                                       .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
6228                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6229                                       .build());
6230 
6231     // Move the swipe a bit
6232     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6233                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6234                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6235                                       .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6236                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6237                                       .build());
6238 
6239     // End the swipe
6240     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
6241                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6242                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6243                                       .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6244                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6245                                       .build());
6246     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
6247                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6248                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6249                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6250                                       .build());
6251     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
6252                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6253                                       .classification(MotionClassification::MULTI_FINGER_SWIPE)
6254                                       .build());
6255 
6256     window->assertNoEvents();
6257 }
6258 
6259 /**
6260  * Send a two-pointer gesture to a single window. The window's orientation changes in response to
6261  * the first pointer.
6262  * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
6263  */
TEST_F(InputDispatcherTest,MultiplePointersWithRotatingWindow)6264 TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
6265     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6266     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6267                                                              ui::LogicalDisplayId::DEFAULT);
6268     window->setFrame(Rect(0, 0, 400, 400));
6269     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6270 
6271     const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
6272     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6273                                       .downTime(baseTime + 10)
6274                                       .eventTime(baseTime + 10)
6275                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6276                                       .build());
6277 
6278     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6279 
6280     // Change the transform so that the orientation is now different from original.
6281     window->setWindowTransform(0, -1, 1, 0);
6282 
6283     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6284 
6285     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6286                                       .downTime(baseTime + 10)
6287                                       .eventTime(baseTime + 30)
6288                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6289                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
6290                                       .build());
6291 
6292     window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
6293 
6294     // Finish the gesture and start a new one. Ensure all events are sent to the window.
6295     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6296                                       .downTime(baseTime + 10)
6297                                       .eventTime(baseTime + 40)
6298                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6299                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
6300                                       .build());
6301 
6302     window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
6303 
6304     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6305                                       .downTime(baseTime + 10)
6306                                       .eventTime(baseTime + 50)
6307                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6308                                       .build());
6309 
6310     window->consumeMotionEvent(WithMotionAction(ACTION_UP));
6311 
6312     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6313                                       .downTime(baseTime + 60)
6314                                       .eventTime(baseTime + 60)
6315                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
6316                                       .build());
6317 
6318     window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6319 }
6320 
6321 /**
6322  * When there are multiple screens, such as screen projection to TV or screen recording, if the
6323  * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
6324  * its coordinates should be converted by the transform of the windows of target screen.
6325  */
TEST_F(InputDispatcherTest,WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay)6326 TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
6327     // This case will create a window and a spy window on the default display and mirror
6328     //  window on the second display. cancel event is sent through spy  window pilferPointers
6329     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6330 
6331     sp<FakeWindowHandle> spyWindowDefaultDisplay =
6332             sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6333                                        ui::LogicalDisplayId::DEFAULT);
6334     spyWindowDefaultDisplay->setTrustedOverlay(true);
6335     spyWindowDefaultDisplay->setSpy(true);
6336 
6337     sp<FakeWindowHandle> windowDefaultDisplay =
6338             sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
6339                                        ui::LogicalDisplayId::DEFAULT);
6340     windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
6341 
6342     sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
6343     windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
6344 
6345     // Add the windows to the dispatcher
6346     mDispatcher->onWindowInfosChanged(
6347             {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
6348               *windowSecondDisplay->getInfo()},
6349              {},
6350              0,
6351              0});
6352 
6353     // Send down to ui::LogicalDisplayId::DEFAULT
6354     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6355               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6356                                ui::LogicalDisplayId::DEFAULT, {100, 100}))
6357             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6358 
6359     spyWindowDefaultDisplay->consumeMotionDown();
6360     windowDefaultDisplay->consumeMotionDown();
6361 
6362     EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
6363 
6364     // windowDefaultDisplay gets cancel
6365     std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
6366     ASSERT_NE(nullptr, event);
6367     EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
6368 
6369     // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
6370     // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
6371     // the x and y coordinates are both 100, otherwise if the cancel event is sent to
6372     // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
6373     EXPECT_EQ(100, event->getX(0));
6374     EXPECT_EQ(100, event->getY(0));
6375 }
6376 
6377 /**
6378  * Ensure the correct coordinate spaces are used by InputDispatcher.
6379  *
6380  * InputDispatcher works in the display space, so its coordinate system is relative to the display
6381  * panel. Windows get events in the window space, and get raw coordinates in the logical display
6382  * space.
6383  */
6384 class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
6385 public:
SetUp()6386     void SetUp() override {
6387         InputDispatcherTest::SetUp();
6388         removeAllWindowsAndDisplays();
6389     }
6390 
addDisplayInfo(ui::LogicalDisplayId displayId,const ui::Transform & transform)6391     void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
6392         gui::DisplayInfo info;
6393         info.displayId = displayId;
6394         info.transform = transform;
6395         mDisplayInfos.push_back(std::move(info));
6396         mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
6397     }
6398 
addWindow(const sp<WindowInfoHandle> & windowHandle)6399     void addWindow(const sp<WindowInfoHandle>& windowHandle) {
6400         mWindowInfos.push_back(*windowHandle->getInfo());
6401         mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
6402     }
6403 
removeAllWindowsAndDisplays()6404     void removeAllWindowsAndDisplays() {
6405         mDisplayInfos.clear();
6406         mWindowInfos.clear();
6407     }
6408 
6409     // Set up a test scenario where the display has a scaled projection and there are two windows
6410     // on the display.
setupScaledDisplayScenario()6411     std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
6412         // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
6413         // respectively.
6414         ui::Transform displayTransform;
6415         displayTransform.set(2, 0, 0, 4);
6416         addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
6417 
6418         std::shared_ptr<FakeApplicationHandle> application =
6419                 std::make_shared<FakeApplicationHandle>();
6420 
6421         // Add two windows to the display. Their frames are represented in the display space.
6422         sp<FakeWindowHandle> firstWindow =
6423                 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6424                                            ui::LogicalDisplayId::DEFAULT);
6425         firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
6426         addWindow(firstWindow);
6427 
6428         sp<FakeWindowHandle> secondWindow =
6429                 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6430                                            ui::LogicalDisplayId::DEFAULT);
6431         secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
6432         addWindow(secondWindow);
6433         return {std::move(firstWindow), std::move(secondWindow)};
6434     }
6435 
6436 private:
6437     std::vector<gui::DisplayInfo> mDisplayInfos;
6438     std::vector<gui::WindowInfo> mWindowInfos;
6439 };
6440 
TEST_F(InputDispatcherDisplayProjectionTest,HitTestCoordinateSpaceConsistency)6441 TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
6442     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6443     // Send down to the first window. The point is represented in the display space. The point is
6444     // selected so that if the hit test was performed with the point and the bounds being in
6445     // different coordinate spaces, the event would end up in the incorrect window.
6446     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6447                                                  AINPUT_SOURCE_TOUCHSCREEN,
6448                                                  ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
6449 
6450     firstWindow->consumeMotionDown();
6451     secondWindow->assertNoEvents();
6452 }
6453 
6454 // Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
6455 // the event should be treated as being in the logical display space.
TEST_F(InputDispatcherDisplayProjectionTest,InjectionInLogicalDisplaySpace)6456 TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
6457     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6458     // Send down to the first window. The point is represented in the logical display space. The
6459     // point is selected so that if the hit test was done in logical display space, then it would
6460     // end up in the incorrect window.
6461     injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
6462                      PointF{75 * 2, 55 * 4});
6463 
6464     firstWindow->consumeMotionDown();
6465     secondWindow->assertNoEvents();
6466 }
6467 
6468 // Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
6469 // event should be treated as being in the logical display space.
TEST_F(InputDispatcherDisplayProjectionTest,InjectionWithTransformInLogicalDisplaySpace)6470 TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
6471     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6472 
6473     const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6474     ui::Transform injectedEventTransform;
6475     injectedEventTransform.set(matrix);
6476     const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
6477     const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
6478 
6479     MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6480                                 .displayId(ui::LogicalDisplayId::DEFAULT)
6481                                 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6482                                 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
6483                                                  .x(untransformedPoint.x)
6484                                                  .y(untransformedPoint.y))
6485                                 .build();
6486     event.transform(matrix);
6487 
6488     injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
6489                       InputEventInjectionSync::WAIT_FOR_RESULT);
6490 
6491     firstWindow->consumeMotionDown();
6492     secondWindow->assertNoEvents();
6493 }
6494 
TEST_F(InputDispatcherDisplayProjectionTest,WindowGetsEventsInCorrectCoordinateSpace)6495 TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
6496     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6497 
6498     // Send down to the second window.
6499     mDispatcher->notifyMotion(
6500             generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6501                                ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
6502 
6503     firstWindow->assertNoEvents();
6504     std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
6505     ASSERT_NE(nullptr, event);
6506     EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
6507 
6508     // Ensure that the events from the "getRaw" API are in logical display coordinates.
6509     EXPECT_EQ(300, event->getRawX(0));
6510     EXPECT_EQ(880, event->getRawY(0));
6511 
6512     // Ensure that the x and y values are in the window's coordinate space.
6513     // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
6514     // the logical display space. This will be the origin of the window space.
6515     EXPECT_EQ(100, event->getX(0));
6516     EXPECT_EQ(80, event->getY(0));
6517 }
6518 
TEST_F(InputDispatcherDisplayProjectionTest,CancelMotionWithCorrectCoordinates)6519 TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
6520     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6521     // The monitor will always receive events in the logical display's coordinate space, because
6522     // it does not have a window.
6523     FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
6524 
6525     // Send down to the first window.
6526     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6527                                                  ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
6528     firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6529     monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6530 
6531     // Second pointer goes down on second window.
6532     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6533                                                  ui::LogicalDisplayId::DEFAULT,
6534                                                  {PointF{50, 100}, PointF{150, 220}}));
6535     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
6536     const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
6537                                                             {1, PointF{300, 880}}};
6538     monitor.consumeMotionEvent(
6539             AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
6540 
6541     mDispatcher->cancelCurrentTouch();
6542 
6543     firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6544     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
6545     monitor.consumeMotionEvent(
6546             AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
6547 }
6548 
TEST_F(InputDispatcherDisplayProjectionTest,SynthesizeDownWithCorrectCoordinates)6549 TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
6550     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6551 
6552     // Send down to the first window.
6553     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6554                                                  ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
6555     firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6556 
6557     // The pointer is transferred to the second window, and the second window receives it in the
6558     // correct coordinate space.
6559     mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
6560     firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6561     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
6562 }
6563 
TEST_F(InputDispatcherDisplayProjectionTest,SynthesizeHoverEnterExitWithCorrectCoordinates)6564 TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
6565     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6566 
6567     // Send hover move to the second window, and ensure it shows up as hover enter.
6568     mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6569                                                  ui::LogicalDisplayId::DEFAULT,
6570                                                  {PointF{150, 220}}));
6571     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6572                                            WithCoords(100, 80), WithRawCoords(300, 880)));
6573 
6574     // Touch down at the same location and ensure a hover exit is synthesized.
6575     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
6576                                                  ui::LogicalDisplayId::DEFAULT,
6577                                                  {PointF{150, 220}}));
6578     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6579                                            WithRawCoords(300, 880)));
6580     secondWindow->consumeMotionEvent(
6581             AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6582     secondWindow->assertNoEvents();
6583     firstWindow->assertNoEvents();
6584 }
6585 
6586 // Same as above, but while the window is being mirrored.
TEST_F(InputDispatcherDisplayProjectionTest,SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored)6587 TEST_F(InputDispatcherDisplayProjectionTest,
6588        SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
6589     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6590 
6591     const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6592     ui::Transform secondDisplayTransform;
6593     secondDisplayTransform.set(matrix);
6594     addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6595 
6596     sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6597     secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6598     addWindow(secondWindowClone);
6599 
6600     // Send hover move to the second window, and ensure it shows up as hover enter.
6601     mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6602                                                  ui::LogicalDisplayId::DEFAULT,
6603                                                  {PointF{150, 220}}));
6604     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6605                                            WithCoords(100, 80), WithRawCoords(300, 880)));
6606 
6607     // Touch down at the same location and ensure a hover exit is synthesized for the correct
6608     // display.
6609     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
6610                                                  ui::LogicalDisplayId::DEFAULT,
6611                                                  {PointF{150, 220}}));
6612     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6613                                            WithRawCoords(300, 880)));
6614     secondWindow->consumeMotionEvent(
6615             AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6616     secondWindow->assertNoEvents();
6617     firstWindow->assertNoEvents();
6618 }
6619 
TEST_F(InputDispatcherDisplayProjectionTest,SynthesizeHoverCancelationWithCorrectCoordinates)6620 TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
6621     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6622 
6623     // Send hover enter to second window
6624     mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
6625                                                  ui::LogicalDisplayId::DEFAULT,
6626                                                  {PointF{150, 220}}));
6627     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6628                                            WithCoords(100, 80), WithRawCoords(300, 880)));
6629 
6630     mDispatcher->cancelCurrentTouch();
6631 
6632     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6633                                            WithRawCoords(300, 880)));
6634     secondWindow->assertNoEvents();
6635     firstWindow->assertNoEvents();
6636 }
6637 
6638 // Same as above, but while the window is being mirrored.
TEST_F(InputDispatcherDisplayProjectionTest,SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored)6639 TEST_F(InputDispatcherDisplayProjectionTest,
6640        SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
6641     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6642 
6643     const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6644     ui::Transform secondDisplayTransform;
6645     secondDisplayTransform.set(matrix);
6646     addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6647 
6648     sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6649     secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6650     addWindow(secondWindowClone);
6651 
6652     // Send hover enter to second window
6653     mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
6654                                                  ui::LogicalDisplayId::DEFAULT,
6655                                                  {PointF{150, 220}}));
6656     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6657                                            WithCoords(100, 80), WithRawCoords(300, 880),
6658                                            WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
6659 
6660     mDispatcher->cancelCurrentTouch();
6661 
6662     // Ensure the cancelation happens with the correct displayId and the correct coordinates.
6663     secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6664                                            WithRawCoords(300, 880),
6665                                            WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
6666     secondWindow->assertNoEvents();
6667     firstWindow->assertNoEvents();
6668 }
6669 
6670 /** Ensure consistent behavior of InputDispatcher in all orientations. */
6671 class InputDispatcherDisplayOrientationFixture
6672       : public InputDispatcherDisplayProjectionTest,
6673         public ::testing::WithParamInterface<ui::Rotation> {};
6674 
6675 // This test verifies the touchable region of a window for all rotations of the display by tapping
6676 // in different locations on the display, specifically points close to the four corners of a
6677 // window.
TEST_P(InputDispatcherDisplayOrientationFixture,HitTestInDifferentOrientations)6678 TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
6679     constexpr static int32_t displayWidth = 400;
6680     constexpr static int32_t displayHeight = 800;
6681 
6682     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6683 
6684     const auto rotation = GetParam();
6685 
6686     // Set up the display with the specified rotation.
6687     const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6688     const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6689     const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6690     const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6691                                          logicalDisplayWidth, logicalDisplayHeight);
6692     addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
6693 
6694     // Create a window with its bounds determined in the logical display.
6695     const Rect frameInLogicalDisplay(100, 100, 200, 300);
6696     const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
6697     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6698                                                              ui::LogicalDisplayId::DEFAULT);
6699     window->setFrame(frameInDisplay, displayTransform);
6700     addWindow(window);
6701 
6702     // The following points in logical display space should be inside the window.
6703     static const std::array<vec2, 4> insidePoints{
6704             {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6705     for (const auto pointInsideWindow : insidePoints) {
6706         const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
6707         const PointF pointInDisplaySpace{p.x, p.y};
6708         mDispatcher->notifyMotion(
6709                 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6710                                    ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6711         window->consumeMotionDown();
6712 
6713         mDispatcher->notifyMotion(
6714                 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6715                                    ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6716         window->consumeMotionUp();
6717     }
6718 
6719     // The following points in logical display space should be outside the window.
6720     static const std::array<vec2, 5> outsidePoints{
6721             {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6722     for (const auto pointOutsideWindow : outsidePoints) {
6723         const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
6724         const PointF pointInDisplaySpace{p.x, p.y};
6725         mDispatcher->notifyMotion(
6726                 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6727                                    ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6728 
6729         mDispatcher->notifyMotion(
6730                 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6731                                    ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6732     }
6733     window->assertNoEvents();
6734 }
6735 
6736 // This test verifies the occlusion detection for all rotations of the display by tapping
6737 // in different locations on the display, specifically points close to the four corners of a
6738 // window.
TEST_P(InputDispatcherDisplayOrientationFixture,BlockUntrustClickInDifferentOrientations)6739 TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
6740     constexpr static int32_t displayWidth = 400;
6741     constexpr static int32_t displayHeight = 800;
6742 
6743     std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
6744             std::make_shared<FakeApplicationHandle>();
6745     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6746 
6747     const auto rotation = GetParam();
6748 
6749     // Set up the display with the specified rotation.
6750     const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6751     const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6752     const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6753     const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6754                                          logicalDisplayWidth, logicalDisplayHeight);
6755     addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
6756 
6757     // Create a window that not trusted.
6758     const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6759 
6760     const Rect untrustedWindowFrameInDisplay =
6761             displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6762 
6763     sp<FakeWindowHandle> untrustedWindow =
6764             sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
6765                                        ui::LogicalDisplayId::DEFAULT);
6766     untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6767     untrustedWindow->setTrustedOverlay(false);
6768     untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6769     untrustedWindow->setTouchable(false);
6770     untrustedWindow->setAlpha(1.0f);
6771     untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6772     addWindow(untrustedWindow);
6773 
6774     // Create a simple app window below the untrusted window.
6775     const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6776     const Rect simpleAppWindowFrameInDisplay =
6777             displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6778 
6779     sp<FakeWindowHandle> simpleAppWindow =
6780             sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
6781                                        ui::LogicalDisplayId::DEFAULT);
6782     simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6783     simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6784     addWindow(simpleAppWindow);
6785 
6786     // The following points in logical display space should be inside the untrusted window, so
6787     // the simple window could not receive events that coordinate is these point.
6788     static const std::array<vec2, 4> untrustedPoints{
6789             {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6790 
6791     for (const auto untrustedPoint : untrustedPoints) {
6792         const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6793         const PointF pointInDisplaySpace{p.x, p.y};
6794         mDispatcher->notifyMotion(
6795                 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6796                                    ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6797         mDispatcher->notifyMotion(
6798                 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6799                                    ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6800     }
6801     untrustedWindow->assertNoEvents();
6802     simpleAppWindow->assertNoEvents();
6803     // The following points in logical display space should be outside the untrusted window, so
6804     // the simple window should receive events that coordinate is these point.
6805     static const std::array<vec2, 5> trustedPoints{
6806             {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6807     for (const auto trustedPoint : trustedPoints) {
6808         const vec2 p = displayTransform.inverse().transform(trustedPoint);
6809         const PointF pointInDisplaySpace{p.x, p.y};
6810         mDispatcher->notifyMotion(
6811                 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6812                                    ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6813         simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6814                                            AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6815         mDispatcher->notifyMotion(
6816                 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6817                                    ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6818         simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6819                                          AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6820     }
6821     untrustedWindow->assertNoEvents();
6822 }
6823 
6824 // Run the precision tests for all rotations.
6825 INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6826                          InputDispatcherDisplayOrientationFixture,
6827                          ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6828                                            ui::ROTATION_270),
__anon345ef8bd0502(const testing::TestParamInfo<ui::Rotation>& testParamInfo) 6829                          [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6830                              return ftl::enum_string(testParamInfo.param);
6831                          });
6832 
6833 using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6834                                             sp<IBinder>, sp<IBinder>)>;
6835 
6836 class TransferTouchFixture : public InputDispatcherTest,
6837                              public ::testing::WithParamInterface<TransferFunction> {};
6838 
TEST_P(TransferTouchFixture,TransferTouch_OnePointer)6839 TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
6840     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6841 
6842     // Create a couple of windows
6843     sp<FakeWindowHandle> firstWindow =
6844             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6845                                        ui::LogicalDisplayId::DEFAULT);
6846     firstWindow->setDupTouchToWallpaper(true);
6847     sp<FakeWindowHandle> secondWindow =
6848             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6849                                        ui::LogicalDisplayId::DEFAULT);
6850     sp<FakeWindowHandle> wallpaper =
6851             sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6852                                        ui::LogicalDisplayId::DEFAULT);
6853     wallpaper->setIsWallpaper(true);
6854     // Add the windows to the dispatcher, and ensure the first window is focused
6855     mDispatcher->onWindowInfosChanged(
6856             {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
6857     setFocusedWindow(firstWindow);
6858     firstWindow->consumeFocusEvent(true);
6859 
6860     // Send down to the first window
6861     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6862                                                  AINPUT_SOURCE_TOUCHSCREEN,
6863                                                  ui::LogicalDisplayId::DEFAULT));
6864 
6865     // Only the first window should get the down event
6866     firstWindow->consumeMotionDown();
6867     secondWindow->assertNoEvents();
6868     wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6869     // Dispatcher reports pointer down outside focus for the wallpaper
6870     mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
6871 
6872     // Transfer touch to the second window
6873     TransferFunction f = GetParam();
6874     const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6875     ASSERT_TRUE(success);
6876     // The first window gets cancel and the second gets down
6877     firstWindow->consumeMotionCancel();
6878     secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6879                                     AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6880     wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6881     // There should not be any changes to the focused window when transferring touch
6882     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
6883 
6884     // Send up event to the second window
6885     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6886                                                  ui::LogicalDisplayId::DEFAULT));
6887     // The first window gets no events and the second gets up
6888     firstWindow->assertNoEvents();
6889     secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6890                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6891     wallpaper->assertNoEvents();
6892 }
6893 
6894 /**
6895  * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6896  * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6897  * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
6898  * natural to the user.
6899  * In this test, we are sending a pointer to both spy window and first window. We then try to
6900  * transfer touch to the second window. The dispatcher should identify the first window as the
6901  * one that should lose the gesture, and therefore the action should be to move the gesture from
6902  * the first window to the second.
6903  * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6904  * to test the other API, as well.
6905  */
TEST_P(TransferTouchFixture,TransferTouch_MultipleWindowsWithSpy)6906 TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6907     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6908 
6909     // Create a couple of windows + a spy window
6910     sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6911                                                                 ui::LogicalDisplayId::DEFAULT);
6912     spyWindow->setTrustedOverlay(true);
6913     spyWindow->setSpy(true);
6914     sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6915                                                                   ui::LogicalDisplayId::DEFAULT);
6916     sp<FakeWindowHandle> secondWindow =
6917             sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6918                                        ui::LogicalDisplayId::DEFAULT);
6919 
6920     // Add the windows to the dispatcher
6921     mDispatcher->onWindowInfosChanged(
6922             {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6923 
6924     // Send down to the first window
6925     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6926                                                  AINPUT_SOURCE_TOUCHSCREEN,
6927                                                  ui::LogicalDisplayId::DEFAULT));
6928     // Only the first window and spy should get the down event
6929     spyWindow->consumeMotionDown();
6930     firstWindow->consumeMotionDown();
6931 
6932     // Transfer touch to the second window. Non-spy window should be preferred over the spy window
6933     // if f === 'transferTouchGesture'.
6934     TransferFunction f = GetParam();
6935     const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6936     ASSERT_TRUE(success);
6937     // The first window gets cancel and the second gets down
6938     firstWindow->consumeMotionCancel();
6939     secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6940                                     AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6941 
6942     // Send up event to the second window
6943     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6944                                                  ui::LogicalDisplayId::DEFAULT));
6945     // The first  window gets no events and the second+spy get up
6946     firstWindow->assertNoEvents();
6947     spyWindow->consumeMotionUp();
6948     secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6949                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6950 }
6951 
TEST_P(TransferTouchFixture,TransferTouch_TwoPointersNonSplitTouch)6952 TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
6953     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6954 
6955     PointF touchPoint = {10, 10};
6956 
6957     // Create a couple of windows
6958     sp<FakeWindowHandle> firstWindow =
6959             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6960                                        ui::LogicalDisplayId::DEFAULT);
6961     firstWindow->setPreventSplitting(true);
6962     sp<FakeWindowHandle> secondWindow =
6963             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6964                                        ui::LogicalDisplayId::DEFAULT);
6965     secondWindow->setPreventSplitting(true);
6966 
6967     // Add the windows to the dispatcher
6968     mDispatcher->onWindowInfosChanged(
6969             {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6970 
6971     // Send down to the first window
6972     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6973                                                  AINPUT_SOURCE_TOUCHSCREEN,
6974                                                  ui::LogicalDisplayId::DEFAULT, {touchPoint}));
6975     // Only the first window should get the down event
6976     firstWindow->consumeMotionDown();
6977     secondWindow->assertNoEvents();
6978 
6979     // Send pointer down to the first window
6980     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6981                                                  ui::LogicalDisplayId::DEFAULT,
6982                                                  {touchPoint, touchPoint}));
6983     // Only the first window should get the pointer down event
6984     firstWindow->consumeMotionPointerDown(1);
6985     secondWindow->assertNoEvents();
6986 
6987     // Transfer touch focus to the second window
6988     TransferFunction f = GetParam();
6989     bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6990     ASSERT_TRUE(success);
6991     // The first window gets cancel and the second gets down and pointer down
6992     firstWindow->consumeMotionCancel();
6993     secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6994                                     AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6995     secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
6996                                            AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6997 
6998     // Send pointer up to the second window
6999     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
7000                                                  ui::LogicalDisplayId::DEFAULT,
7001                                                  {touchPoint, touchPoint}));
7002     // The first window gets nothing and the second gets pointer up
7003     firstWindow->assertNoEvents();
7004     secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
7005                                          AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
7006                                                WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
7007                                                WithPointerCount(2)));
7008 
7009     // Send up event to the second window
7010     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
7011                                                  ui::LogicalDisplayId::DEFAULT));
7012     // The first window gets nothing and the second gets up
7013     firstWindow->assertNoEvents();
7014     secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7015                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7016 }
7017 
TEST_P(TransferTouchFixture,TransferTouch_MultipleWallpapers)7018 TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
7019     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7020 
7021     // Create a couple of windows
7022     sp<FakeWindowHandle> firstWindow =
7023             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
7024                                        ui::LogicalDisplayId::DEFAULT);
7025     firstWindow->setDupTouchToWallpaper(true);
7026     sp<FakeWindowHandle> secondWindow =
7027             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
7028                                        ui::LogicalDisplayId::DEFAULT);
7029     secondWindow->setDupTouchToWallpaper(true);
7030 
7031     sp<FakeWindowHandle> wallpaper1 =
7032             sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
7033                                        ui::LogicalDisplayId::DEFAULT);
7034     wallpaper1->setIsWallpaper(true);
7035 
7036     sp<FakeWindowHandle> wallpaper2 =
7037             sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
7038                                        ui::LogicalDisplayId::DEFAULT);
7039     wallpaper2->setIsWallpaper(true);
7040     // Add the windows to the dispatcher
7041     mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
7042                                         *secondWindow->getInfo(), *wallpaper2->getInfo()},
7043                                        {},
7044                                        0,
7045                                        0});
7046 
7047     // Send down to the first window
7048     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7049                                                  AINPUT_SOURCE_TOUCHSCREEN,
7050                                                  ui::LogicalDisplayId::DEFAULT));
7051 
7052     // Only the first window should get the down event
7053     firstWindow->consumeMotionDown();
7054     secondWindow->assertNoEvents();
7055     wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
7056     wallpaper2->assertNoEvents();
7057 
7058     // Transfer touch focus to the second window
7059     TransferFunction f = GetParam();
7060     bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
7061     ASSERT_TRUE(success);
7062 
7063     // The first window gets cancel and the second gets down
7064     firstWindow->consumeMotionCancel();
7065     secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
7066                                     AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7067     wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
7068     wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
7069                                   EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7070 
7071     // Send up event to the second window
7072     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
7073                                                  ui::LogicalDisplayId::DEFAULT));
7074     // The first  window gets no events and the second gets up
7075     firstWindow->assertNoEvents();
7076     secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7077                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7078     wallpaper1->assertNoEvents();
7079     wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7080                                 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7081 }
7082 
7083 // For the cases of single pointer touch and two pointers non-split touch, the api's
7084 // 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
7085 // for the case where there are multiple pointers split across several windows.
7086 INSTANTIATE_TEST_SUITE_P(
7087         InputDispatcherTransferFunctionTests, TransferTouchFixture,
7088         ::testing::Values(
7089                 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
__anon345ef8bd0602(const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> , sp<IBinder> destChannelToken) 7090                     sp<IBinder> destChannelToken) {
7091                     return dispatcher->transferTouchOnDisplay(destChannelToken,
7092                                                               ui::LogicalDisplayId::DEFAULT);
7093                 },
7094                 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
__anon345ef8bd0702(const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from, sp<IBinder> to) 7095                     sp<IBinder> to) {
7096                     return dispatcher->transferTouchGesture(from, to,
7097                                                             /*isDragAndDrop=*/false);
7098                 }));
7099 
TEST_F(InputDispatcherTest,TransferTouch_TwoPointersSplitTouch)7100 TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
7101     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7102 
7103     sp<FakeWindowHandle> firstWindow =
7104             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
7105                                        ui::LogicalDisplayId::DEFAULT);
7106     firstWindow->setFrame(Rect(0, 0, 600, 400));
7107 
7108     sp<FakeWindowHandle> secondWindow =
7109             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
7110                                        ui::LogicalDisplayId::DEFAULT);
7111     secondWindow->setFrame(Rect(0, 400, 600, 800));
7112 
7113     // Add the windows to the dispatcher
7114     mDispatcher->onWindowInfosChanged(
7115             {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7116 
7117     PointF pointInFirst = {300, 200};
7118     PointF pointInSecond = {300, 600};
7119 
7120     // Send down to the first window
7121     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7122                                                  AINPUT_SOURCE_TOUCHSCREEN,
7123                                                  ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
7124     // Only the first window should get the down event
7125     firstWindow->consumeMotionDown();
7126     secondWindow->assertNoEvents();
7127 
7128     // Send down to the second window
7129     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7130                                                  ui::LogicalDisplayId::DEFAULT,
7131                                                  {pointInFirst, pointInSecond}));
7132     // The first window gets a move and the second a down
7133     firstWindow->consumeMotionMove();
7134     secondWindow->consumeMotionDown();
7135 
7136     // Transfer touch to the second window
7137     mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
7138     // The first window gets cancel and the new gets pointer down (it already saw down)
7139     firstWindow->consumeMotionCancel();
7140     secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
7141                                            AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7142 
7143     // Send pointer up to the second window
7144     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
7145                                                  ui::LogicalDisplayId::DEFAULT,
7146                                                  {pointInFirst, pointInSecond}));
7147     // The first window gets nothing and the second gets pointer up
7148     firstWindow->assertNoEvents();
7149     secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
7150                                          AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
7151                                                WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
7152                                                WithPointerCount(2)));
7153 
7154     // Send up event to the second window
7155     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
7156                                                  ui::LogicalDisplayId::DEFAULT));
7157     // The first window gets nothing and the second gets up
7158     firstWindow->assertNoEvents();
7159     secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7160                                   AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7161 }
7162 
7163 // Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
7164 // Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
7165 // receiving touch is not supported, so the touch should continue on those windows and the
7166 // transferred-to window should get nothing.
TEST_F(InputDispatcherTest,TransferTouchOnDisplay_TwoPointersSplitTouch)7167 TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
7168     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7169 
7170     sp<FakeWindowHandle> firstWindow =
7171             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
7172                                        ui::LogicalDisplayId::DEFAULT);
7173     firstWindow->setFrame(Rect(0, 0, 600, 400));
7174 
7175     sp<FakeWindowHandle> secondWindow =
7176             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
7177                                        ui::LogicalDisplayId::DEFAULT);
7178     secondWindow->setFrame(Rect(0, 400, 600, 800));
7179 
7180     // Add the windows to the dispatcher
7181     mDispatcher->onWindowInfosChanged(
7182             {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7183 
7184     PointF pointInFirst = {300, 200};
7185     PointF pointInSecond = {300, 600};
7186 
7187     // Send down to the first window
7188     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7189                                                  AINPUT_SOURCE_TOUCHSCREEN,
7190                                                  ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
7191     // Only the first window should get the down event
7192     firstWindow->consumeMotionDown();
7193     secondWindow->assertNoEvents();
7194 
7195     // Send down to the second window
7196     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7197                                                  ui::LogicalDisplayId::DEFAULT,
7198                                                  {pointInFirst, pointInSecond}));
7199     // The first window gets a move and the second a down
7200     firstWindow->consumeMotionMove();
7201     secondWindow->consumeMotionDown();
7202 
7203     // Transfer touch focus to the second window
7204     const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
7205                                                                  ui::LogicalDisplayId::DEFAULT);
7206     // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
7207     ASSERT_FALSE(transferred);
7208     firstWindow->assertNoEvents();
7209     secondWindow->assertNoEvents();
7210 
7211     // The rest of the dispatch should proceed as normal
7212     // Send pointer up to the second window
7213     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
7214                                                  ui::LogicalDisplayId::DEFAULT,
7215                                                  {pointInFirst, pointInSecond}));
7216     // The first window gets MOVE and the second gets pointer up
7217     firstWindow->consumeMotionMove();
7218     secondWindow->consumeMotionUp();
7219 
7220     // Send up event to the first window
7221     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
7222                                                  ui::LogicalDisplayId::DEFAULT));
7223     // The first window gets nothing and the second gets up
7224     firstWindow->consumeMotionUp();
7225     secondWindow->assertNoEvents();
7226 }
7227 
7228 // This case will create two windows and one mirrored window on the default display and mirror
7229 // two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
7230 // the windows info of second display before default display.
TEST_F(InputDispatcherTest,TransferTouch_CloneSurface)7231 TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
7232     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7233     sp<FakeWindowHandle> firstWindowInPrimary =
7234             sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
7235                                        ui::LogicalDisplayId::DEFAULT);
7236     firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
7237     sp<FakeWindowHandle> secondWindowInPrimary =
7238             sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
7239                                        ui::LogicalDisplayId::DEFAULT);
7240     secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
7241 
7242     sp<FakeWindowHandle> mirrorWindowInPrimary =
7243             firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
7244     mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
7245 
7246     sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
7247     firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
7248 
7249     sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
7250     secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
7251 
7252     // Update window info, let it find window handle of second display first.
7253     mDispatcher->onWindowInfosChanged(
7254             {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
7255               *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
7256               *secondWindowInPrimary->getInfo()},
7257              {},
7258              0,
7259              0});
7260 
7261     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7262               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7263                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
7264             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7265 
7266     // Window should receive motion event.
7267     firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7268 
7269     // Transfer touch
7270     ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
7271                                                   secondWindowInPrimary->getToken()));
7272     // The first window gets cancel.
7273     firstWindowInPrimary->consumeMotionCancel();
7274     secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
7275                                              AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7276 
7277     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7278               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7279                                 ui::LogicalDisplayId::DEFAULT, {150, 50}))
7280             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7281     firstWindowInPrimary->assertNoEvents();
7282     secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
7283                                              AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7284 
7285     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7286               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
7287                              {150, 50}))
7288             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7289     firstWindowInPrimary->assertNoEvents();
7290     secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7291                                            AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7292 }
7293 
7294 // Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
7295 // 'transferTouchOnDisplay' api.
TEST_F(InputDispatcherTest,TransferTouchOnDisplay_CloneSurface)7296 TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
7297     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7298     sp<FakeWindowHandle> firstWindowInPrimary =
7299             sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
7300                                        ui::LogicalDisplayId::DEFAULT);
7301     firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
7302     sp<FakeWindowHandle> secondWindowInPrimary =
7303             sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
7304                                        ui::LogicalDisplayId::DEFAULT);
7305     secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
7306 
7307     sp<FakeWindowHandle> mirrorWindowInPrimary =
7308             firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
7309     mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
7310 
7311     sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
7312     firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
7313 
7314     sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
7315     secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
7316 
7317     // Update window info, let it find window handle of second display first.
7318     mDispatcher->onWindowInfosChanged(
7319             {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
7320               *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
7321               *secondWindowInPrimary->getInfo()},
7322              {},
7323              0,
7324              0});
7325 
7326     // Touch on second display.
7327     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7328               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7329                                {50, 50}))
7330             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7331 
7332     // Window should receive motion event.
7333     firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7334 
7335     // Transfer touch focus
7336     ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
7337                                                     SECOND_DISPLAY_ID));
7338 
7339     // The first window gets cancel.
7340     firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7341     secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
7342                                                AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7343 
7344     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7345               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7346                                 SECOND_DISPLAY_ID, {150, 50}))
7347             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7348     firstWindowInSecondary->assertNoEvents();
7349     secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
7350                                                AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7351 
7352     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7353               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
7354             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7355     firstWindowInSecondary->assertNoEvents();
7356     secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7357 }
7358 
TEST_F(InputDispatcherTest,FocusedWindow_ReceivesFocusEventAndKeyEvent)7359 TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
7360     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7361     sp<FakeWindowHandle> window =
7362             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7363                                        ui::LogicalDisplayId::DEFAULT);
7364 
7365     window->setFocusable(true);
7366     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7367     setFocusedWindow(window);
7368 
7369     window->consumeFocusEvent(true);
7370 
7371     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
7372 
7373     // Window should receive key down event.
7374     window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
7375 
7376     // Should have poked user activity
7377     mDispatcher->waitForIdle();
7378     mFakePolicy->assertUserActivityPoked();
7379 }
7380 
TEST_F(InputDispatcherTest,FocusedWindow_DisableUserActivity)7381 TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
7382     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7383     sp<FakeWindowHandle> window =
7384             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7385                                        ui::LogicalDisplayId::DEFAULT);
7386 
7387     window->setDisableUserActivity(true);
7388     window->setFocusable(true);
7389     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7390     setFocusedWindow(window);
7391 
7392     window->consumeFocusEvent(true);
7393 
7394     mDispatcher->notifyKey(
7395             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7396 
7397     // Window should receive key down event.
7398     window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
7399 
7400     // Should have not poked user activity
7401     mDispatcher->waitForIdle();
7402     mFakePolicy->assertUserActivityNotPoked();
7403 }
7404 
TEST_F(InputDispatcherTest,FocusedWindow_DoesNotReceivePolicyConsumedKey)7405 TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
7406     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7407     sp<FakeWindowHandle> window =
7408             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7409                                        ui::LogicalDisplayId::DEFAULT);
7410 
7411     window->setFocusable(true);
7412     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7413     setFocusedWindow(window);
7414 
7415     window->consumeFocusEvent(true);
7416 
7417     mFakePolicy->setConsumeKeyBeforeDispatching(true);
7418 
7419     mDispatcher->notifyKey(
7420             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7421     mDispatcher->waitForIdle();
7422 
7423     // Key is not passed down
7424     window->assertNoEvents();
7425 
7426     // Should have poked user activity
7427     mFakePolicy->assertUserActivityPoked();
7428 }
7429 
TEST_F(InputDispatcherTest,FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity)7430 TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
7431     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7432     sp<FakeWindowHandle> window =
7433             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7434                                        ui::LogicalDisplayId::DEFAULT);
7435 
7436     window->setDisableUserActivity(true);
7437     window->setFocusable(true);
7438     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7439     setFocusedWindow(window);
7440 
7441     window->consumeFocusEvent(true);
7442 
7443     mFakePolicy->setConsumeKeyBeforeDispatching(true);
7444 
7445     mDispatcher->notifyKey(
7446             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7447     mDispatcher->waitForIdle();
7448 
7449     // System key is not passed down
7450     window->assertNoEvents();
7451 
7452     // Should have poked user activity
7453     mFakePolicy->assertUserActivityPoked();
7454 }
7455 
7456 class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
7457                                                public ::testing::WithParamInterface<bool> {};
7458 
TEST_P(DisableUserActivityInputDispatcherTest,NotPassedToUserUserActivity)7459 TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
7460     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7461     sp<FakeWindowHandle> window =
7462             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7463                                        ui::LogicalDisplayId::DEFAULT);
7464 
7465     window->setDisableUserActivity(GetParam());
7466 
7467     window->setFocusable(true);
7468     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7469     setFocusedWindow(window);
7470 
7471     window->consumeFocusEvent(true);
7472 
7473     mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7474                                    .keyCode(AKEYCODE_A)
7475                                    .policyFlags(0)
7476                                    .build());
7477     mDispatcher->waitForIdle();
7478 
7479     // Key is not passed down
7480     window->assertNoEvents();
7481 
7482     // Should not have poked user activity
7483     mFakePolicy->assertUserActivityNotPoked();
7484 }
7485 
7486 INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
7487                         ::testing::Bool());
7488 
TEST_F(InputDispatcherTest,InjectedTouchesPokeUserActivity)7489 TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
7490     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7491     sp<FakeWindowHandle> window =
7492             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7493                                        ui::LogicalDisplayId::DEFAULT);
7494 
7495     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7496 
7497     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7498               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7499                                 ui::LogicalDisplayId::DEFAULT, {100, 100}))
7500             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7501 
7502     window->consumeMotionEvent(
7503             AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
7504 
7505     // Should have poked user activity
7506     mDispatcher->waitForIdle();
7507     mFakePolicy->assertUserActivityPoked();
7508 }
7509 
TEST_F(InputDispatcherTest,UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent)7510 TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
7511     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7512     sp<FakeWindowHandle> window =
7513             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7514                                        ui::LogicalDisplayId::DEFAULT);
7515 
7516     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7517 
7518     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
7519     mDispatcher->waitForIdle();
7520 
7521     window->assertNoEvents();
7522 }
7523 
7524 // If a window is touchable, but does not have focus, it should receive motion events, but not keys
TEST_F(InputDispatcherTest,UnfocusedWindow_ReceivesMotionsButNotKeys)7525 TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
7526     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7527     sp<FakeWindowHandle> window =
7528             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7529                                        ui::LogicalDisplayId::DEFAULT);
7530 
7531     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7532 
7533     // Send key
7534     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
7535     // Send motion
7536     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7537                                                  AINPUT_SOURCE_TOUCHSCREEN,
7538                                                  ui::LogicalDisplayId::DEFAULT));
7539 
7540     // Window should receive only the motion event
7541     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7542     window->assertNoEvents(); // Key event or focus event will not be received
7543 }
7544 
TEST_F(InputDispatcherTest,PointerCancel_SendCancelWhenSplitTouch)7545 TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
7546     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7547 
7548     sp<FakeWindowHandle> firstWindow =
7549             sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
7550                                        ui::LogicalDisplayId::DEFAULT);
7551     firstWindow->setFrame(Rect(0, 0, 600, 400));
7552 
7553     sp<FakeWindowHandle> secondWindow =
7554             sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
7555                                        ui::LogicalDisplayId::DEFAULT);
7556     secondWindow->setFrame(Rect(0, 400, 600, 800));
7557 
7558     // Add the windows to the dispatcher
7559     mDispatcher->onWindowInfosChanged(
7560             {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7561 
7562     PointF pointInFirst = {300, 200};
7563     PointF pointInSecond = {300, 600};
7564 
7565     // Send down to the first window
7566     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7567                                                  AINPUT_SOURCE_TOUCHSCREEN,
7568                                                  ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
7569     // Only the first window should get the down event
7570     firstWindow->consumeMotionDown();
7571     secondWindow->assertNoEvents();
7572 
7573     // Send down to the second window
7574     mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7575                                                  ui::LogicalDisplayId::DEFAULT,
7576                                                  {pointInFirst, pointInSecond}));
7577     // The first window gets a move and the second a down
7578     firstWindow->consumeMotionMove();
7579     secondWindow->consumeMotionDown();
7580 
7581     // Send pointer cancel to the second window
7582     NotifyMotionArgs pointerUpMotionArgs =
7583             generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
7584                                ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
7585     pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
7586     mDispatcher->notifyMotion(pointerUpMotionArgs);
7587     // The first window gets move and the second gets cancel.
7588     firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7589     secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7590 
7591     // Send up event.
7592     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
7593                                                  ui::LogicalDisplayId::DEFAULT));
7594     // The first window gets up and the second gets nothing.
7595     firstWindow->consumeMotionUp();
7596     secondWindow->assertNoEvents();
7597 }
7598 
TEST_F(InputDispatcherTest,SendTimeline_DoesNotCrashDispatcher)7599 TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
7600     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7601 
7602     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
7603                                                              ui::LogicalDisplayId::DEFAULT);
7604     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7605     std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
7606     graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
7607     graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
7608 
7609     window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
7610     window->assertNoEvents();
7611     mDispatcher->waitForIdle();
7612 }
7613 
7614 using InputDispatcherMonitorTest = InputDispatcherTest;
7615 
7616 /**
7617  * Two entities that receive touch: A window, and a global monitor.
7618  * The touch goes to the window, and then the window disappears.
7619  * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
7620  * for the monitor, as well.
7621  * 1. foregroundWindow
7622  * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
7623  */
TEST_F(InputDispatcherMonitorTest,MonitorTouchIsCanceledWhenForegroundWindowDisappears)7624 TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
7625     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7626     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7627                                                              ui::LogicalDisplayId::DEFAULT);
7628 
7629     FakeMonitorReceiver monitor =
7630             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
7631 
7632     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7633     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7634               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7635                                ui::LogicalDisplayId::DEFAULT, {100, 200}))
7636             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7637 
7638     // Both the foreground window and the global monitor should receive the touch down
7639     window->consumeMotionDown();
7640     monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7641 
7642     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7643               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7644                                 ui::LogicalDisplayId::DEFAULT, {110, 200}))
7645             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7646 
7647     window->consumeMotionMove();
7648     monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7649 
7650     // Now the foreground window goes away
7651     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7652     window->consumeMotionCancel();
7653     monitor.assertNoEvents(); // Global monitor does not get a cancel yet
7654 
7655     // If more events come in, there will be no more foreground window to send them to. This will
7656     // cause a cancel for the monitor, as well.
7657     ASSERT_EQ(InputEventInjectionResult::FAILED,
7658               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7659                                 ui::LogicalDisplayId::DEFAULT, {120, 200}))
7660             << "Injection should fail because the window was removed";
7661     window->assertNoEvents();
7662     // Global monitor now gets the cancel
7663     monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
7664 }
7665 
TEST_F(InputDispatcherMonitorTest,ReceivesMotionEvents)7666 TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
7667     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7668     sp<FakeWindowHandle> window =
7669             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7670                                        ui::LogicalDisplayId::DEFAULT);
7671     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7672 
7673     FakeMonitorReceiver monitor =
7674             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
7675 
7676     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7677               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7678                                ui::LogicalDisplayId::DEFAULT))
7679             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7680     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7681     monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7682 }
7683 
TEST_F(InputDispatcherMonitorTest,MonitorCannotPilferPointers)7684 TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
7685     FakeMonitorReceiver monitor =
7686             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
7687 
7688     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7689     sp<FakeWindowHandle> window =
7690             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7691                                        ui::LogicalDisplayId::DEFAULT);
7692     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7693 
7694     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7695               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7696                                ui::LogicalDisplayId::DEFAULT))
7697             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7698     monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7699     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7700 
7701     // Pilfer pointers from the monitor.
7702     // This should not do anything and the window should continue to receive events.
7703     EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
7704 
7705     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7706               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7707                                 ui::LogicalDisplayId::DEFAULT))
7708             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7709 
7710     monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7711     window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7712 }
7713 
TEST_F(InputDispatcherMonitorTest,NoWindowTransform)7714 TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
7715     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7716     sp<FakeWindowHandle> window =
7717             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7718                                        ui::LogicalDisplayId::DEFAULT);
7719     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7720     window->setWindowOffset(20, 40);
7721     window->setWindowTransform(0, 1, -1, 0);
7722 
7723     FakeMonitorReceiver monitor =
7724             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
7725 
7726     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7727               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7728                                ui::LogicalDisplayId::DEFAULT))
7729             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7730     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7731     std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
7732     ASSERT_NE(nullptr, event);
7733     // Even though window has transform, gesture monitor must not.
7734     ASSERT_EQ(ui::Transform(), event->getTransform());
7735 }
7736 
TEST_F(InputDispatcherMonitorTest,InjectionFailsWithNoWindow)7737 TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
7738     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7739     FakeMonitorReceiver monitor =
7740             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
7741 
7742     ASSERT_EQ(InputEventInjectionResult::FAILED,
7743               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7744                                ui::LogicalDisplayId::DEFAULT))
7745             << "Injection should fail if there is a monitor, but no touchable window";
7746     monitor.assertNoEvents();
7747 }
7748 
7749 /**
7750  * Two displays
7751  * The first monitor has a foreground window, a monitor
7752  * The second window has only one monitor.
7753  * We first inject a Down event into the first display, this injection should succeed and both
7754  * the foreground window and monitor should receive a down event, then inject a Down event into
7755  * the second display as well, this injection should fail, at this point, the first display
7756  * window and monitor should not receive a cancel or any other event.
7757  * Continue to inject Move and UP events to the first display, the events should be received
7758  * normally by the foreground window and monitor.
7759  */
TEST_F(InputDispatcherMonitorTest,MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents)7760 TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
7761     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7762     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7763                                                              ui::LogicalDisplayId::DEFAULT);
7764 
7765     FakeMonitorReceiver monitor =
7766             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
7767     FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7768 
7769     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7770     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7771               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7772                                ui::LogicalDisplayId::DEFAULT, {100, 200}))
7773             << "The down event injected into the first display should succeed";
7774 
7775     window->consumeMotionDown();
7776     monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7777 
7778     ASSERT_EQ(InputEventInjectionResult::FAILED,
7779               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7780                                {100, 200}))
7781             << "The down event injected into the second display should fail since there's no "
7782                "touchable window";
7783 
7784     // Continue to inject event to first display.
7785     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7786               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7787                                 ui::LogicalDisplayId::DEFAULT, {110, 220}))
7788             << "The move event injected into the first display should succeed";
7789 
7790     window->consumeMotionMove();
7791     monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7792 
7793     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7794               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
7795                              {110, 220}))
7796             << "The up event injected into the first display should succeed";
7797 
7798     window->consumeMotionUp();
7799     monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7800 
7801     window->assertNoEvents();
7802     monitor.assertNoEvents();
7803     secondMonitor.assertNoEvents();
7804 }
7805 
7806 /**
7807  * Two displays
7808  * There is a monitor and foreground window on each display.
7809  * First, we inject down events into each of the two displays, at this point, the foreground windows
7810  * and monitors on both displays should receive down events.
7811  * At this point, the foreground window of the second display goes away, the gone window should
7812  * receive the cancel event, and the other windows and monitors should not receive any events.
7813  * Inject a move event into the second display. At this point, the injection should fail because
7814  * the second display no longer has a foreground window. At this point, the monitor on the second
7815  * display should receive a cancel event, and any windows or monitors on the first display should
7816  * not receive any events, and any subsequent injection of events into the second display should
7817  * also fail.
7818  * Continue to inject events into the first display, and the events should all be injected
7819  * successfully and received normally.
7820  */
TEST_F(InputDispatcherMonitorTest,MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled)7821 TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7822     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7823     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7824                                                              ui::LogicalDisplayId::DEFAULT);
7825     sp<FakeWindowHandle> secondWindow =
7826             sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7827                                        SECOND_DISPLAY_ID);
7828 
7829     FakeMonitorReceiver monitor =
7830             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
7831     FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7832 
7833     // There is a foreground window on both displays.
7834     mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7835     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7836               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7837                                ui::LogicalDisplayId::DEFAULT, {100, 200}))
7838             << "The down event injected into the first display should succeed";
7839 
7840     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7841     monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7842 
7843     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7844               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7845                                {100, 200}))
7846             << "The down event injected into the second display should succeed";
7847 
7848     secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7849     secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7850 
7851     // Now second window is gone away.
7852     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7853 
7854     // The gone window should receive a cancel, and the monitor on the second display should not
7855     // receive any events.
7856     secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7857     secondMonitor.assertNoEvents();
7858 
7859     ASSERT_EQ(InputEventInjectionResult::FAILED,
7860               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7861                                 SECOND_DISPLAY_ID, {110, 220}))
7862             << "The move event injected into the second display should fail because there's no "
7863                "touchable window";
7864     // Now the monitor on the second display should receive a cancel event.
7865     secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
7866 
7867     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7868               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7869                                 ui::LogicalDisplayId::DEFAULT, {110, 200}))
7870             << "The move event injected into the first display should succeed";
7871 
7872     window->consumeMotionMove();
7873     monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7874 
7875     ASSERT_EQ(InputEventInjectionResult::FAILED,
7876               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7877                              {110, 220}))
7878             << "The up event injected into the second display should fail because there's no "
7879                "touchable window";
7880 
7881     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7882               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
7883                              {110, 220}))
7884             << "The up event injected into the first display should succeed";
7885 
7886     window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7887     monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7888 
7889     window->assertNoEvents();
7890     monitor.assertNoEvents();
7891     secondWindow->assertNoEvents();
7892     secondMonitor.assertNoEvents();
7893 }
7894 
7895 /**
7896  * One display with transform
7897  * There is a foreground window and a monitor on the display
7898  * Inject down event and move event sequentially, the foreground window and monitor can receive down
7899  * event and move event, then let the foreground window go away, the foreground window receives
7900  * cancel event, inject move event again, the monitor receives cancel event, all the events received
7901  * by the monitor should be with the same transform as the display
7902  */
TEST_F(InputDispatcherMonitorTest,MonitorTouchCancelEventWithDisplayTransform)7903 TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7904     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7905     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7906                                                              ui::LogicalDisplayId::DEFAULT);
7907     FakeMonitorReceiver monitor =
7908             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
7909 
7910     ui::Transform transform;
7911     transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7912 
7913     gui::DisplayInfo displayInfo;
7914     displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
7915     displayInfo.transform = transform;
7916 
7917     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7918 
7919     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7920               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7921                                ui::LogicalDisplayId::DEFAULT, {100, 200}))
7922             << "The down event injected should succeed";
7923 
7924     window->consumeMotionDown();
7925     std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7926     EXPECT_EQ(transform, downMotionEvent->getTransform());
7927     EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7928 
7929     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7930               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7931                                 ui::LogicalDisplayId::DEFAULT, {110, 220}))
7932             << "The move event injected should succeed";
7933 
7934     window->consumeMotionMove();
7935     std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7936     EXPECT_EQ(transform, moveMotionEvent->getTransform());
7937     EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7938 
7939     // Let foreground window gone
7940     mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7941 
7942     // Foreground window should receive a cancel event, but not the monitor.
7943     window->consumeMotionCancel();
7944 
7945     ASSERT_EQ(InputEventInjectionResult::FAILED,
7946               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7947                                 ui::LogicalDisplayId::DEFAULT, {110, 220}))
7948             << "The move event injected should failed";
7949     // Now foreground should not receive any events, but monitor should receive a cancel event
7950     // with transform that same as display's display.
7951     std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7952     EXPECT_EQ(transform, cancelMotionEvent->getTransform());
7953     EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
7954     EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7955 
7956     // Other event inject to this display should fail.
7957     ASSERT_EQ(InputEventInjectionResult::FAILED,
7958               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
7959                                 ui::LogicalDisplayId::DEFAULT, {110, 220}))
7960             << "The up event injected should fail because the touched window was removed";
7961     window->assertNoEvents();
7962     monitor.assertNoEvents();
7963 }
7964 
TEST_F(InputDispatcherTest,TestMoveEvent)7965 TEST_F(InputDispatcherTest, TestMoveEvent) {
7966     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7967     sp<FakeWindowHandle> window =
7968             sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7969                                        ui::LogicalDisplayId::DEFAULT);
7970 
7971     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7972 
7973     NotifyMotionArgs motionArgs =
7974             generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7975                                ui::LogicalDisplayId::DEFAULT);
7976 
7977     mDispatcher->notifyMotion(motionArgs);
7978     // Window should receive motion down event.
7979     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7980 
7981     motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
7982     motionArgs.id += 1;
7983     motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7984     motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7985                                              motionArgs.pointerCoords[0].getX() - 10);
7986 
7987     mDispatcher->notifyMotion(motionArgs);
7988     window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
7989 }
7990 
7991 /**
7992  * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7993  * the device default right away. In the test scenario, we check both the default value,
7994  * and the action of enabling / disabling.
7995  */
TEST_F(InputDispatcherTest,TouchModeState_IsSentToApps)7996 TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
7997     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7998     sp<FakeWindowHandle> window =
7999             sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
8000                                        ui::LogicalDisplayId::DEFAULT);
8001     const WindowInfo& windowInfo = *window->getInfo();
8002 
8003     // Set focused application.
8004     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8005     window->setFocusable(true);
8006 
8007     SCOPED_TRACE("Check default value of touch mode");
8008     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8009     setFocusedWindow(window);
8010     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
8011 
8012     SCOPED_TRACE("Remove the window to trigger focus loss");
8013     window->setFocusable(false);
8014     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8015     window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
8016 
8017     SCOPED_TRACE("Disable touch mode");
8018     mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
8019                                 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
8020     window->consumeTouchModeEvent(false);
8021     window->setFocusable(true);
8022     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8023     setFocusedWindow(window);
8024     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
8025 
8026     SCOPED_TRACE("Remove the window to trigger focus loss");
8027     window->setFocusable(false);
8028     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8029     window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
8030 
8031     SCOPED_TRACE("Enable touch mode again");
8032     mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
8033                                 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
8034     window->consumeTouchModeEvent(true);
8035     window->setFocusable(true);
8036     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8037     setFocusedWindow(window);
8038     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
8039 
8040     window->assertNoEvents();
8041 }
8042 
TEST_F(InputDispatcherTest,VerifyInputEvent_KeyEvent)8043 TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
8044     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8045     sp<FakeWindowHandle> window =
8046             sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
8047                                        ui::LogicalDisplayId::DEFAULT);
8048 
8049     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8050     window->setFocusable(true);
8051 
8052     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8053     setFocusedWindow(window);
8054 
8055     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
8056 
8057     const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
8058     mDispatcher->notifyKey(keyArgs);
8059 
8060     std::unique_ptr<KeyEvent> event = window->consumeKey();
8061     ASSERT_NE(event, nullptr);
8062     std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
8063     ASSERT_NE(verified, nullptr);
8064     ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
8065 
8066     ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
8067     ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
8068     ASSERT_EQ(keyArgs.source, verified->source);
8069     ASSERT_EQ(keyArgs.displayId, verified->displayId);
8070 
8071     const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
8072 
8073     ASSERT_EQ(keyArgs.action, verifiedKey.action);
8074     ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
8075     ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
8076     ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
8077     ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
8078     ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
8079     ASSERT_EQ(0, verifiedKey.repeatCount);
8080 }
8081 
TEST_F(InputDispatcherTest,VerifyInputEvent_MotionEvent)8082 TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
8083     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8084     sp<FakeWindowHandle> window =
8085             sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
8086                                        ui::LogicalDisplayId::DEFAULT);
8087 
8088     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8089 
8090     ui::Transform transform;
8091     transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
8092 
8093     gui::DisplayInfo displayInfo;
8094     displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
8095     displayInfo.transform = transform;
8096 
8097     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
8098 
8099     const NotifyMotionArgs motionArgs =
8100             generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8101                                ui::LogicalDisplayId::DEFAULT);
8102     mDispatcher->notifyMotion(motionArgs);
8103 
8104     std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
8105     ASSERT_NE(nullptr, event);
8106     std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
8107     ASSERT_NE(verified, nullptr);
8108     ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
8109 
8110     EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
8111     EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
8112     EXPECT_EQ(motionArgs.source, verified->source);
8113     EXPECT_EQ(motionArgs.displayId, verified->displayId);
8114 
8115     const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
8116 
8117     const vec2 rawXY =
8118             MotionEvent::calculateTransformedXY(motionArgs.source, transform,
8119                                                 motionArgs.pointerCoords[0].getXYValue());
8120     EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
8121     EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
8122     EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
8123     EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
8124     EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
8125     EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
8126     EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
8127 }
8128 
8129 /**
8130  * Ensure that separate calls to sign the same data are generating the same key.
8131  * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
8132  * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
8133  * tests.
8134  */
TEST_F(InputDispatcherTest,GeneratedHmac_IsConsistent)8135 TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
8136     KeyEvent event = getTestKeyEvent();
8137     VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
8138 
8139     std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
8140     std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
8141     ASSERT_EQ(hmac1, hmac2);
8142 }
8143 
8144 /**
8145  * Ensure that changes in VerifiedKeyEvent produce a different hmac.
8146  */
TEST_F(InputDispatcherTest,GeneratedHmac_ChangesWhenFieldsChange)8147 TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
8148     KeyEvent event = getTestKeyEvent();
8149     VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
8150     std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
8151 
8152     verifiedEvent.deviceId += 1;
8153     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8154 
8155     verifiedEvent.source += 1;
8156     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8157 
8158     verifiedEvent.eventTimeNanos += 1;
8159     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8160 
8161     verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
8162     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8163 
8164     verifiedEvent.action += 1;
8165     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8166 
8167     verifiedEvent.downTimeNanos += 1;
8168     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8169 
8170     verifiedEvent.flags += 1;
8171     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8172 
8173     verifiedEvent.keyCode += 1;
8174     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8175 
8176     verifiedEvent.scanCode += 1;
8177     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8178 
8179     verifiedEvent.metaState += 1;
8180     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8181 
8182     verifiedEvent.repeatCount += 1;
8183     ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8184 }
8185 
TEST_F(InputDispatcherTest,SetFocusedWindow)8186 TEST_F(InputDispatcherTest, SetFocusedWindow) {
8187     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8188     sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8189                                                                 ui::LogicalDisplayId::DEFAULT);
8190     sp<FakeWindowHandle> windowSecond =
8191             sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8192                                        ui::LogicalDisplayId::DEFAULT);
8193     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8194 
8195     // Top window is also focusable but is not granted focus.
8196     windowTop->setFocusable(true);
8197     windowSecond->setFocusable(true);
8198     mDispatcher->onWindowInfosChanged(
8199             {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
8200     setFocusedWindow(windowSecond);
8201 
8202     windowSecond->consumeFocusEvent(true);
8203     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
8204             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8205 
8206     // Focused window should receive event.
8207     windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
8208     windowTop->assertNoEvents();
8209 }
8210 
TEST_F(InputDispatcherTest,SetFocusedWindow_DropRequestInvalidChannel)8211 TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
8212     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8213     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8214                                                              ui::LogicalDisplayId::DEFAULT);
8215     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8216 
8217     window->setFocusable(true);
8218     // Release channel for window is no longer valid.
8219     window->releaseChannel();
8220     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8221     setFocusedWindow(window);
8222 
8223     // Test inject a key down, should timeout.
8224     ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
8225 
8226     // window channel is invalid, so it should not receive any input event.
8227     window->assertNoEvents();
8228 }
8229 
TEST_F(InputDispatcherTest,SetFocusedWindow_DropRequestNoFocusableWindow)8230 TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
8231     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8232     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8233                                                              ui::LogicalDisplayId::DEFAULT);
8234     window->setFocusable(false);
8235     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8236 
8237     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8238     setFocusedWindow(window);
8239 
8240     // Test inject a key down, should timeout.
8241     ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
8242 
8243     // window is not focusable, so it should not receive any input event.
8244     window->assertNoEvents();
8245 }
8246 
TEST_F(InputDispatcherTest,SetFocusedWindow_CheckFocusedToken)8247 TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
8248     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8249     sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8250                                                                 ui::LogicalDisplayId::DEFAULT);
8251     sp<FakeWindowHandle> windowSecond =
8252             sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8253                                        ui::LogicalDisplayId::DEFAULT);
8254     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8255 
8256     windowTop->setFocusable(true);
8257     windowSecond->setFocusable(true);
8258     mDispatcher->onWindowInfosChanged(
8259             {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
8260     setFocusedWindow(windowTop);
8261     windowTop->consumeFocusEvent(true);
8262 
8263     windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
8264     mDispatcher->onWindowInfosChanged(
8265             {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
8266     windowSecond->consumeFocusEvent(true);
8267     windowTop->consumeFocusEvent(false);
8268 
8269     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
8270             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8271 
8272     // Focused window should receive event.
8273     windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
8274 }
8275 
TEST_F(InputDispatcherTest,SetFocusedWindow_TransferFocusTokenNotFocusable)8276 TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
8277     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8278     sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8279                                                                 ui::LogicalDisplayId::DEFAULT);
8280     sp<FakeWindowHandle> windowSecond =
8281             sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8282                                        ui::LogicalDisplayId::DEFAULT);
8283     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8284 
8285     windowTop->setFocusable(true);
8286     windowSecond->setFocusable(false);
8287     windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
8288     mDispatcher->onWindowInfosChanged(
8289             {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
8290     setFocusedWindow(windowTop);
8291     windowTop->consumeFocusEvent(true);
8292 
8293     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
8294             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8295 
8296     // Event should be dropped.
8297     windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
8298     windowSecond->assertNoEvents();
8299 }
8300 
TEST_F(InputDispatcherTest,SetFocusedWindow_DeferInvisibleWindow)8301 TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
8302     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8303     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8304                                                              ui::LogicalDisplayId::DEFAULT);
8305     sp<FakeWindowHandle> previousFocusedWindow =
8306             sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
8307                                        ui::LogicalDisplayId::DEFAULT);
8308     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8309 
8310     window->setFocusable(true);
8311     previousFocusedWindow->setFocusable(true);
8312     window->setVisible(false);
8313     mDispatcher->onWindowInfosChanged(
8314             {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
8315     setFocusedWindow(previousFocusedWindow);
8316     previousFocusedWindow->consumeFocusEvent(true);
8317 
8318     // Requesting focus on invisible window takes focus from currently focused window.
8319     setFocusedWindow(window);
8320     previousFocusedWindow->consumeFocusEvent(false);
8321 
8322     // Injected key goes to pending queue.
8323     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8324               injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8325                         ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
8326 
8327     // Window does not get focus event or key down.
8328     window->assertNoEvents();
8329 
8330     // Window becomes visible.
8331     window->setVisible(true);
8332     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8333 
8334     // Window receives focus event.
8335     window->consumeFocusEvent(true);
8336     // Focused window receives key down.
8337     window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
8338 }
8339 
TEST_F(InputDispatcherTest,DisplayRemoved)8340 TEST_F(InputDispatcherTest, DisplayRemoved) {
8341     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8342     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
8343                                                              ui::LogicalDisplayId::DEFAULT);
8344     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8345 
8346     // window is granted focus.
8347     window->setFocusable(true);
8348     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8349     setFocusedWindow(window);
8350     window->consumeFocusEvent(true);
8351 
8352     // When a display is removed window loses focus.
8353     mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
8354     window->consumeFocusEvent(false);
8355 }
8356 
8357 /**
8358  * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
8359  * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
8360  * of the 'slipperyEnterWindow'.
8361  *
8362  * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
8363  * a way so that the touched location is no longer covered by the top window.
8364  *
8365  * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
8366  * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
8367  * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
8368  * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
8369  * with ACTION_DOWN).
8370  * Thus, the touch has been transferred from the top window into the bottom window, because the top
8371  * window moved itself away from the touched location and had Flag::SLIPPERY.
8372  *
8373  * Even though the top window moved away from the touched location, it is still obscuring the bottom
8374  * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
8375  * OBSCURED should be set for the MotionEvent that reaches the bottom window.
8376  *
8377  * In this test, we ensure that the event received by the bottom window has
8378  * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
8379  */
TEST_F(InputDispatcherTest,SlipperyWindow_SetsFlagPartiallyObscured)8380 TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
8381     constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
8382     constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
8383 
8384     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8385     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
8386 
8387     sp<FakeWindowHandle> slipperyExitWindow =
8388             sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8389                                        ui::LogicalDisplayId::DEFAULT);
8390     slipperyExitWindow->setSlippery(true);
8391     // Make sure this one overlaps the bottom window
8392     slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
8393     // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
8394     // one. Windows with the same owner are not considered to be occluding each other.
8395     slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
8396 
8397     sp<FakeWindowHandle> slipperyEnterWindow =
8398             sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8399                                        ui::LogicalDisplayId::DEFAULT);
8400     slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
8401 
8402     mDispatcher->onWindowInfosChanged(
8403             {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
8404 
8405     // Use notifyMotion instead of injecting to avoid dealing with injection permissions
8406     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8407                                                  AINPUT_SOURCE_TOUCHSCREEN,
8408                                                  ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
8409     slipperyExitWindow->consumeMotionDown();
8410     slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
8411     mDispatcher->onWindowInfosChanged(
8412             {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
8413 
8414     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
8415                                                  AINPUT_SOURCE_TOUCHSCREEN,
8416                                                  ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
8417 
8418     slipperyExitWindow->consumeMotionCancel();
8419 
8420     slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
8421                                            AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8422 }
8423 
8424 /**
8425  * Two windows, one on the left and another on the right. The left window is slippery. The right
8426  * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
8427  * touch moves from the left window into the right window, the gesture should continue to go to the
8428  * left window. Touch shouldn't slip because the right window can't receive touches. This test
8429  * reproduces a crash.
8430  */
TEST_F(InputDispatcherTest,TouchSlippingIntoWindowThatDropsTouches)8431 TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
8432     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8433 
8434     sp<FakeWindowHandle> leftSlipperyWindow =
8435             sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8436                                        ui::LogicalDisplayId::DEFAULT);
8437     leftSlipperyWindow->setSlippery(true);
8438     leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
8439 
8440     sp<FakeWindowHandle> rightDropTouchesWindow =
8441             sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8442                                        ui::LogicalDisplayId::DEFAULT);
8443     rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
8444     rightDropTouchesWindow->setDropInput(true);
8445 
8446     mDispatcher->onWindowInfosChanged(
8447             {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
8448 
8449     // Start touch in the left window
8450     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8451                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8452                                       .build());
8453     leftSlipperyWindow->consumeMotionDown();
8454 
8455     // And move it into the right window
8456     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8457                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8458                                       .build());
8459 
8460     // Since the right window isn't eligible to receive input, touch does not slip.
8461     // The left window continues to receive the gesture.
8462     leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8463     rightDropTouchesWindow->assertNoEvents();
8464 }
8465 
8466 /**
8467  * A single window is on screen first. Touch is injected into that window. Next, a second window
8468  * appears. Since the first window is slippery, touch will move from the first window to the second.
8469  */
TEST_F(InputDispatcherTest,InjectedTouchSlips)8470 TEST_F(InputDispatcherTest, InjectedTouchSlips) {
8471     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8472     sp<FakeWindowHandle> originalWindow =
8473             sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
8474                                        ui::LogicalDisplayId::DEFAULT);
8475     originalWindow->setFrame(Rect(0, 0, 200, 200));
8476     originalWindow->setSlippery(true);
8477 
8478     sp<FakeWindowHandle> appearingWindow =
8479             sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
8480                                        ui::LogicalDisplayId::DEFAULT);
8481     appearingWindow->setFrame(Rect(0, 0, 200, 200));
8482 
8483     mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
8484 
8485     // Touch down on the original window
8486     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8487               injectMotionEvent(*mDispatcher,
8488                                 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8489                                         .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
8490                                         .build()));
8491     originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8492 
8493     // Now, a new window appears. This could be, for example, a notification shade that appears
8494     // after user starts to drag down on the launcher window.
8495     mDispatcher->onWindowInfosChanged(
8496             {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
8497     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8498               injectMotionEvent(*mDispatcher,
8499                                 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8500                                         .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
8501                                         .build()));
8502     originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8503     appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8504     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8505               injectMotionEvent(*mDispatcher,
8506                                 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8507                                         .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
8508                                         .build()));
8509     appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8510 
8511     originalWindow->assertNoEvents();
8512     appearingWindow->assertNoEvents();
8513 }
8514 
8515 /**
8516  * Three windows:
8517  * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
8518  * - right window
8519  * - spy window
8520  * The three windows do not overlap.
8521  *
8522  * We have two devices reporting events:
8523  * - Device A reports ACTION_DOWN, which lands in the left window
8524  * - Device B reports ACTION_DOWN, which lands in the spy window.
8525  * - Now, device B reports ACTION_MOVE events which move to the right window.
8526  *
8527  * The right window should not receive any events because the spy window is not a foreground window,
8528  * and also it does not support slippery touches.
8529  */
TEST_F(InputDispatcherTest,MultiDeviceSpyWindowSlipTest)8530 TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
8531     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8532     sp<FakeWindowHandle> leftWindow =
8533             sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
8534                                        ui::LogicalDisplayId::DEFAULT);
8535     leftWindow->setFrame(Rect(0, 0, 100, 100));
8536     leftWindow->setSlippery(true);
8537 
8538     sp<FakeWindowHandle> rightWindow =
8539             sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
8540                                        ui::LogicalDisplayId::DEFAULT);
8541     rightWindow->setFrame(Rect(100, 0, 200, 100));
8542 
8543     sp<FakeWindowHandle> spyWindow =
8544             sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8545                                        ui::LogicalDisplayId::DEFAULT);
8546     spyWindow->setFrame(Rect(200, 0, 300, 100));
8547     spyWindow->setSpy(true);
8548     spyWindow->setTrustedOverlay(true);
8549 
8550     mDispatcher->onWindowInfosChanged(
8551             {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
8552 
8553     const DeviceId deviceA = 9;
8554     const DeviceId deviceB = 3;
8555 
8556     // Tap on left window with device A
8557     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8558                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8559                                       .deviceId(deviceA)
8560                                       .build());
8561     leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8562 
8563     // Tap on spy window with device B
8564     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8565                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8566                                       .deviceId(deviceB)
8567                                       .build());
8568     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8569 
8570     // Move to right window with device B. Touches should not slip to the right window, because spy
8571     // window is not a foreground window, and it does not have FLAG_SLIPPERY
8572     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8573                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8574                                       .deviceId(deviceB)
8575                                       .build());
8576     leftWindow->assertNoEvents();
8577     rightWindow->assertNoEvents();
8578     spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8579 }
8580 
8581 /**
8582  * Three windows arranged horizontally and without any overlap.
8583  * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
8584  *
8585  * We have two devices reporting events:
8586  * - Device A reports ACTION_DOWN which lands in the left window
8587  * - Device B reports ACTION_DOWN which lands in the right window
8588  * - Device B reports ACTION_MOVE that shifts to the middle window.
8589  * This should cause touches for Device B to slip from the right window to the middle window.
8590  * The right window should receive ACTION_CANCEL for device B and the
8591  * middle window should receive down event for Device B.
8592  * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
8593  */
TEST_F(InputDispatcherTest,MultiDeviceSlipperyWindowTest)8594 TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
8595     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
8596     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8597     sp<FakeWindowHandle> leftWindow =
8598             sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
8599                                        ui::LogicalDisplayId::DEFAULT);
8600     leftWindow->setFrame(Rect(0, 0, 100, 100));
8601     leftWindow->setSlippery(true);
8602 
8603     sp<FakeWindowHandle> middleWindow =
8604             sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
8605                                        ui::LogicalDisplayId::DEFAULT);
8606     middleWindow->setFrame(Rect(100, 0, 200, 100));
8607 
8608     sp<FakeWindowHandle> rightWindow =
8609             sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
8610                                        ui::LogicalDisplayId::DEFAULT);
8611     rightWindow->setFrame(Rect(200, 0, 300, 100));
8612     rightWindow->setSlippery(true);
8613 
8614     mDispatcher->onWindowInfosChanged(
8615             {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
8616              {},
8617              0,
8618              0});
8619 
8620     const DeviceId deviceA = 9;
8621     const DeviceId deviceB = 3;
8622 
8623     // Tap on left window with device A
8624     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8625                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8626                                       .deviceId(deviceA)
8627                                       .build());
8628     leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8629 
8630     // Tap on right window with device B
8631     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8632                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8633                                       .deviceId(deviceB)
8634                                       .build());
8635     rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8636 
8637     // Move to middle window with device B. Touches should slip to middle window, because right
8638     // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
8639     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8640                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8641                                       .deviceId(deviceB)
8642                                       .build());
8643     rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
8644     middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8645 
8646     // Move to middle window with device A. Touches should slip to middle window, because left
8647     // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
8648     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8649                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8650                                       .deviceId(deviceA)
8651                                       .build());
8652     leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
8653     middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8654 
8655     // Ensure that middle window can receive the remaining move events.
8656     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8657                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
8658                                       .deviceId(deviceB)
8659                                       .build());
8660     leftWindow->assertNoEvents();
8661     middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8662     rightWindow->assertNoEvents();
8663 }
8664 
TEST_F(InputDispatcherTest,NotifiesDeviceInteractionsWithMotions)8665 TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
8666     using Uid = gui::Uid;
8667     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8668 
8669     sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8670                                                                  ui::LogicalDisplayId::DEFAULT);
8671     leftWindow->setFrame(Rect(0, 0, 100, 100));
8672     leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
8673 
8674     sp<FakeWindowHandle> rightSpy =
8675             sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
8676                                        ui::LogicalDisplayId::DEFAULT);
8677     rightSpy->setFrame(Rect(100, 0, 200, 100));
8678     rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
8679     rightSpy->setSpy(true);
8680     rightSpy->setTrustedOverlay(true);
8681 
8682     sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8683                                                                   ui::LogicalDisplayId::DEFAULT);
8684     rightWindow->setFrame(Rect(100, 0, 200, 100));
8685     rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
8686 
8687     mDispatcher->onWindowInfosChanged(
8688             {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
8689 
8690     // Touch in the left window
8691     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8692                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8693                                       .build());
8694     ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
8695     mDispatcher->waitForIdle();
8696     ASSERT_NO_FATAL_FAILURE(
8697             mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
8698 
8699     // Touch another finger over the right windows
8700     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8701                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8702                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8703                                       .build());
8704     ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
8705     ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
8706     ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
8707     mDispatcher->waitForIdle();
8708     ASSERT_NO_FATAL_FAILURE(
8709             mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
8710                                                                 {Uid{101}, Uid{102}, Uid{103}}));
8711 
8712     // Release finger over left window. The UP actions are not treated as device interaction.
8713     // The windows that did not receive the UP pointer will receive MOVE events, but since this
8714     // is part of the UP action, we do not treat this as device interaction.
8715     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
8716                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8717                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8718                                       .build());
8719     ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
8720     ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8721     ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8722     mDispatcher->waitForIdle();
8723     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8724 
8725     // Move remaining finger
8726     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8727                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8728                                       .build());
8729     ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8730     ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8731     mDispatcher->waitForIdle();
8732     ASSERT_NO_FATAL_FAILURE(
8733             mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
8734 
8735     // Release all fingers
8736     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8737                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8738                                       .build());
8739     ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
8740     ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
8741     mDispatcher->waitForIdle();
8742     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8743 }
8744 
TEST_F(InputDispatcherTest,NotifiesDeviceInteractionsWithKeys)8745 TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
8746     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8747 
8748     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8749                                                              ui::LogicalDisplayId::DEFAULT);
8750     window->setFrame(Rect(0, 0, 100, 100));
8751     window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
8752 
8753     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8754     setFocusedWindow(window);
8755     ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
8756 
8757     mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
8758     ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
8759     mDispatcher->waitForIdle();
8760     ASSERT_NO_FATAL_FAILURE(
8761             mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
8762 
8763     // The UP actions are not treated as device interaction.
8764     mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
8765     ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
8766     mDispatcher->waitForIdle();
8767     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8768 }
8769 
TEST_F(InputDispatcherTest,HoverEnterExitSynthesisUsesNewEventId)8770 TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
8771     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8772 
8773     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
8774                                                            ui::LogicalDisplayId::DEFAULT);
8775     left->setFrame(Rect(0, 0, 100, 100));
8776     sp<FakeWindowHandle> right =
8777             sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8778                                        ui::LogicalDisplayId::DEFAULT);
8779     right->setFrame(Rect(100, 0, 200, 100));
8780     sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8781                                                           ui::LogicalDisplayId::DEFAULT);
8782     spy->setFrame(Rect(0, 0, 200, 100));
8783     spy->setTrustedOverlay(true);
8784     spy->setSpy(true);
8785 
8786     mDispatcher->onWindowInfosChanged(
8787             {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8788 
8789     // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
8790     NotifyMotionArgs notifyArgs =
8791             generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8792                                ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
8793     mDispatcher->notifyMotion(notifyArgs);
8794 
8795     std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
8796             AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8797                   WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8798     ASSERT_NE(nullptr, leftEnter);
8799     spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8800                                   Not(WithEventId(notifyArgs.id)),
8801                                   Not(WithEventId(leftEnter->getId())),
8802                                   WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8803 
8804     // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
8805     notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8806                                     ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
8807     mDispatcher->notifyMotion(notifyArgs);
8808 
8809     std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
8810             AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8811                   WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8812     ASSERT_NE(nullptr, leftExit);
8813     right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8814                                     Not(WithEventId(notifyArgs.id)),
8815                                     Not(WithEventId(leftExit->getId())),
8816                                     WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8817 
8818     spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8819 }
8820 
8821 /**
8822  * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8823  * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8824  * the previous window should receive this event and not be dropped.
8825  */
TEST_F(InputDispatcherMultiDeviceTest,SingleDevicePointerDownEventRetentionWithoutWindowTarget)8826 TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
8827     SCOPED_FLAG_OVERRIDE(split_all_touches, false);
8828     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8829     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8830                                                              ui::LogicalDisplayId::DEFAULT);
8831     window->setFrame(Rect(0, 0, 100, 100));
8832     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8833 
8834     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8835                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8836                                       .build());
8837 
8838     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8839 
8840     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8841                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8842                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8843                                       .build());
8844 
8845     window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8846 }
8847 
8848 /**
8849  * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8850  * also reports a DOWN event, which lands in the location of a non-existing window, then the
8851  * previous window should receive deviceB's event and it should be dropped.
8852  */
TEST_F(InputDispatcherMultiDeviceTest,SecondDeviceDownEventDroppedWithoutWindowTarget)8853 TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8854     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8855     sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8856                                                              ui::LogicalDisplayId::DEFAULT);
8857     window->setFrame(Rect(0, 0, 100, 100));
8858     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8859 
8860     const DeviceId deviceA = 9;
8861     const DeviceId deviceB = 3;
8862 
8863     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8864                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8865                                       .deviceId(deviceA)
8866                                       .build());
8867     window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8868 
8869     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8870                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8871                                       .deviceId(deviceB)
8872                                       .build());
8873     window->assertNoEvents();
8874 }
8875 
8876 class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8877 protected:
8878     std::shared_ptr<FakeApplicationHandle> mApp;
8879     sp<FakeWindowHandle> mWindow;
8880 
SetUp()8881     virtual void SetUp() override {
8882         InputDispatcherTest::SetUp();
8883 
8884         mApp = std::make_shared<FakeApplicationHandle>();
8885 
8886         mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8887                                              ui::LogicalDisplayId::DEFAULT);
8888         mWindow->setFrame(Rect(0, 0, 100, 100));
8889 
8890         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8891         setFocusedWindow(mWindow);
8892         ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8893     }
8894 
setFallback(int32_t keycode)8895     void setFallback(int32_t keycode) {
8896         mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8897             return KeyEventBuilder(event).keyCode(keycode).build();
8898         });
8899     }
8900 
consumeKey(bool handled,const::testing::Matcher<KeyEvent> & matcher)8901     void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
8902         std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8903         ASSERT_NE(nullptr, event);
8904         ASSERT_THAT(*event, matcher);
8905     }
8906 };
8907 
TEST_F(InputDispatcherFallbackKeyTest,PolicyNotNotifiedForHandledKey)8908 TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8909     mDispatcher->notifyKey(
8910             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8911     consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8912     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8913 }
8914 
TEST_F(InputDispatcherFallbackKeyTest,PolicyNotifiedForUnhandledKey)8915 TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8916     mDispatcher->notifyKey(
8917             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8918     consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8919     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8920 }
8921 
TEST_F(InputDispatcherFallbackKeyTest,NoFallbackRequestedByPolicy)8922 TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8923     mDispatcher->notifyKey(
8924             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8925 
8926     // Do not handle this key event.
8927     consumeKey(/*handled=*/false,
8928                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8929     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8930 
8931     // Since the policy did not request any fallback to be generated, ensure there are no events.
8932     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8933 }
8934 
TEST_F(InputDispatcherFallbackKeyTest,FallbackDispatchForUnhandledKey)8935 TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8936     setFallback(AKEYCODE_B);
8937     mDispatcher->notifyKey(
8938             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8939 
8940     // Do not handle this key event.
8941     consumeKey(/*handled=*/false,
8942                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8943 
8944     // Since the key was not handled, ensure the fallback event was dispatched instead.
8945     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8946     consumeKey(/*handled=*/true,
8947                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8948                      WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8949 
8950     // Release the original key, and ensure the fallback key is also released.
8951     mDispatcher->notifyKey(
8952             KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8953     consumeKey(/*handled=*/false,
8954                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8955     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8956     consumeKey(/*handled=*/true,
8957                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8958                      WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8959 
8960     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8961     mWindow->assertNoEvents();
8962 }
8963 
TEST_F(InputDispatcherFallbackKeyTest,AppHandlesPreviouslyUnhandledKey)8964 TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8965     setFallback(AKEYCODE_B);
8966     mDispatcher->notifyKey(
8967             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8968 
8969     // Do not handle this key event, but handle the fallback.
8970     consumeKey(/*handled=*/false,
8971                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8972     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8973     consumeKey(/*handled=*/true,
8974                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8975                      WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8976 
8977     // Release the original key, and ensure the fallback key is also released.
8978     mDispatcher->notifyKey(
8979             KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8980     // But this time, the app handles the original key.
8981     consumeKey(/*handled=*/true,
8982                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8983     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8984     // Ensure the fallback key is canceled.
8985     consumeKey(/*handled=*/true,
8986                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8987                      WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8988 
8989     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8990     mWindow->assertNoEvents();
8991 }
8992 
TEST_F(InputDispatcherFallbackKeyTest,AppDoesNotHandleFallback)8993 TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8994     setFallback(AKEYCODE_B);
8995     mDispatcher->notifyKey(
8996             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8997 
8998     // Do not handle this key event.
8999     consumeKey(/*handled=*/false,
9000                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9001     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9002     // App does not handle the fallback either, so ensure another fallback is not generated.
9003     setFallback(AKEYCODE_C);
9004     consumeKey(/*handled=*/false,
9005                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9006                      WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9007 
9008     // Release the original key, and ensure the fallback key is also released.
9009     setFallback(AKEYCODE_B);
9010     mDispatcher->notifyKey(
9011             KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9012     consumeKey(/*handled=*/false,
9013                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9014     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9015     consumeKey(/*handled=*/false,
9016                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9017                      WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9018 
9019     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
9020     mWindow->assertNoEvents();
9021 }
9022 
TEST_F(InputDispatcherFallbackKeyTest,InconsistentPolicyCancelsFallback)9023 TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
9024     setFallback(AKEYCODE_B);
9025     mDispatcher->notifyKey(
9026             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9027 
9028     // Do not handle this key event, so fallback is generated.
9029     consumeKey(/*handled=*/false,
9030                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9031     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9032     consumeKey(/*handled=*/true,
9033                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9034                      WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9035 
9036     // Release the original key, but assume the policy is misbehaving and it
9037     // generates an inconsistent fallback to the one from the DOWN event.
9038     setFallback(AKEYCODE_C);
9039     mDispatcher->notifyKey(
9040             KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9041     consumeKey(/*handled=*/false,
9042                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9043     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9044     // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
9045     consumeKey(/*handled=*/true,
9046                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9047                      WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9048 
9049     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
9050     mWindow->assertNoEvents();
9051 }
9052 
TEST_F(InputDispatcherFallbackKeyTest,CanceledKeyCancelsFallback)9053 TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
9054     setFallback(AKEYCODE_B);
9055     mDispatcher->notifyKey(
9056             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9057 
9058     // Do not handle this key event, so fallback is generated.
9059     consumeKey(/*handled=*/false,
9060                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9061     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9062     consumeKey(/*handled=*/true,
9063                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9064                      WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9065 
9066     // The original key is canceled.
9067     mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
9068                                    .keyCode(AKEYCODE_A)
9069                                    .addFlag(AKEY_EVENT_FLAG_CANCELED)
9070                                    .build());
9071     consumeKey(/*handled=*/false,
9072                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
9073                      WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9074     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9075     // Ensure the fallback key is also canceled due to the original key being canceled.
9076     consumeKey(/*handled=*/true,
9077                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9078                      WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9079 
9080     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
9081     mWindow->assertNoEvents();
9082 }
9083 
TEST_F(InputDispatcherFallbackKeyTest,InputChannelRemovedDuringPolicyCall)9084 TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
9085     setFallback(AKEYCODE_B);
9086     mDispatcher->notifyKey(
9087             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9088 
9089     // Do not handle this key event.
9090     consumeKey(/*handled=*/false,
9091                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9092     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9093     consumeKey(/*handled=*/true,
9094                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9095                      WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9096 
9097     mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
9098         // When the unhandled key is reported to the policy next, remove the input channel.
9099         mDispatcher->removeInputChannel(mWindow->getToken());
9100         return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
9101     });
9102     // Release the original key, and let the app now handle the previously unhandled key.
9103     // This should result in the previously generated fallback key to be cancelled.
9104     // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
9105     // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
9106     // without holding the lock, because it need to synchronously fetch the fallback key. While in
9107     // the policy call, we will now remove the input channel. Once the policy call returns, the
9108     // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
9109     // not cause any crashes.
9110     mDispatcher->notifyKey(
9111             KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9112     consumeKey(/*handled=*/true,
9113                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9114     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9115 }
9116 
TEST_F(InputDispatcherFallbackKeyTest,WindowRemovedDuringPolicyCall)9117 TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
9118     setFallback(AKEYCODE_B);
9119     mDispatcher->notifyKey(
9120             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9121 
9122     // Do not handle this key event.
9123     consumeKey(/*handled=*/false,
9124                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9125     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9126     consumeKey(/*handled=*/true,
9127                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9128                      WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9129 
9130     mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
9131         // When the unhandled key is reported to the policy next, remove the window.
9132         mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9133         return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
9134     });
9135     // Release the original key, which the app will not handle. When this unhandled key is reported
9136     // to the policy, the window will be removed.
9137     mDispatcher->notifyKey(
9138             KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9139     consumeKey(/*handled=*/false,
9140                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9141     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9142 
9143     // Since the window was removed, it loses focus, and the channel state will be reset.
9144     consumeKey(/*handled=*/true,
9145                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9146                      WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9147     mWindow->consumeFocusEvent(false);
9148     mWindow->assertNoEvents();
9149 }
9150 
TEST_F(InputDispatcherFallbackKeyTest,WindowRemovedWhileAwaitingFinishedSignal)9151 TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
9152     setFallback(AKEYCODE_B);
9153     mDispatcher->notifyKey(
9154             KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9155 
9156     // Do not handle this key event.
9157     consumeKey(/*handled=*/false,
9158                AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9159     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9160     const auto [seq, event] = mWindow->receiveEvent();
9161     ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
9162     ASSERT_EQ(event->getType(), InputEventType::KEY);
9163     ASSERT_THAT(static_cast<const KeyEvent&>(*event),
9164                 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9165                       WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9166 
9167     // Remove the window now, which should generate a cancellations and make the window lose focus.
9168     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9169     consumeKey(/*handled=*/true,
9170                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
9171                      WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9172     consumeKey(/*handled=*/true,
9173                AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9174                      WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9175     mWindow->consumeFocusEvent(false);
9176 
9177     // Finish the event by reporting it as handled.
9178     mWindow->finishEvent(*seq);
9179     mWindow->assertNoEvents();
9180 }
9181 
9182 class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
9183 protected:
9184     static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
9185     static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
9186     static constexpr bool KEY_REPEAT_ENABLED = true;
9187 
9188     std::shared_ptr<FakeApplicationHandle> mApp;
9189     sp<FakeWindowHandle> mWindow;
9190 
SetUp()9191     virtual void SetUp() override {
9192         InputDispatcherTest::SetUp();
9193 
9194         mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY,
9195                                                KEY_REPEAT_ENABLED);
9196         setUpWindow();
9197     }
9198 
setUpWindow()9199     void setUpWindow() {
9200         mApp = std::make_shared<FakeApplicationHandle>();
9201         mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
9202                                              ui::LogicalDisplayId::DEFAULT);
9203 
9204         mWindow->setFocusable(true);
9205         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9206         setFocusedWindow(mWindow);
9207         mWindow->consumeFocusEvent(true);
9208     }
9209 
sendAndConsumeKeyDown(int32_t deviceId)9210     void sendAndConsumeKeyDown(int32_t deviceId) {
9211         NotifyKeyArgs keyArgs =
9212                 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
9213         keyArgs.deviceId = deviceId;
9214         keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
9215         mDispatcher->notifyKey(keyArgs);
9216 
9217         // Window should receive key down event.
9218         mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
9219     }
9220 
expectKeyRepeatOnce(int32_t repeatCount)9221     void expectKeyRepeatOnce(int32_t repeatCount) {
9222         SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
9223         mWindow->consumeKeyEvent(
9224                 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
9225     }
9226 
sendAndConsumeKeyUp(int32_t deviceId)9227     void sendAndConsumeKeyUp(int32_t deviceId) {
9228         NotifyKeyArgs keyArgs =
9229                 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
9230         keyArgs.deviceId = deviceId;
9231         keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
9232         mDispatcher->notifyKey(keyArgs);
9233 
9234         // Window should receive key down event.
9235         mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
9236                               /*expectedFlags=*/0);
9237     }
9238 
injectKeyRepeat(int32_t repeatCount)9239     void injectKeyRepeat(int32_t repeatCount) {
9240         ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9241                   injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
9242                             ui::LogicalDisplayId::DEFAULT))
9243                 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9244     }
9245 };
9246 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_ReceivesKeyRepeat)9247 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
9248     sendAndConsumeKeyDown(/*deviceId=*/1);
9249     for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9250         expectKeyRepeatOnce(repeatCount);
9251     }
9252 }
9253 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_ReceivesKeyRepeatFromTwoDevices)9254 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
9255     sendAndConsumeKeyDown(/*deviceId=*/1);
9256     for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9257         expectKeyRepeatOnce(repeatCount);
9258     }
9259     sendAndConsumeKeyDown(/*deviceId=*/2);
9260     /* repeatCount will start from 1 for deviceId 2 */
9261     for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9262         expectKeyRepeatOnce(repeatCount);
9263     }
9264 }
9265 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_StopsKeyRepeatAfterUp)9266 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
9267     sendAndConsumeKeyDown(/*deviceId=*/1);
9268     expectKeyRepeatOnce(/*repeatCount=*/1);
9269     sendAndConsumeKeyUp(/*deviceId=*/1);
9270     mWindow->assertNoEvents();
9271 }
9272 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp)9273 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
9274     sendAndConsumeKeyDown(/*deviceId=*/1);
9275     expectKeyRepeatOnce(/*repeatCount=*/1);
9276     sendAndConsumeKeyDown(/*deviceId=*/2);
9277     expectKeyRepeatOnce(/*repeatCount=*/1);
9278     // Stale key up from device 1.
9279     sendAndConsumeKeyUp(/*deviceId=*/1);
9280     // Device 2 is still down, keep repeating
9281     expectKeyRepeatOnce(/*repeatCount=*/2);
9282     expectKeyRepeatOnce(/*repeatCount=*/3);
9283     // Device 2 key up
9284     sendAndConsumeKeyUp(/*deviceId=*/2);
9285     mWindow->assertNoEvents();
9286 }
9287 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp)9288 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
9289     sendAndConsumeKeyDown(/*deviceId=*/1);
9290     expectKeyRepeatOnce(/*repeatCount=*/1);
9291     sendAndConsumeKeyDown(/*deviceId=*/2);
9292     expectKeyRepeatOnce(/*repeatCount=*/1);
9293     // Device 2 which holds the key repeating goes up, expect the repeating to stop.
9294     sendAndConsumeKeyUp(/*deviceId=*/2);
9295     // Device 1 still holds key down, but the repeating was already stopped
9296     mWindow->assertNoEvents();
9297 }
9298 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_StopsKeyRepeatAfterDisableInputDevice)9299 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
9300     sendAndConsumeKeyDown(DEVICE_ID);
9301     expectKeyRepeatOnce(/*repeatCount=*/1);
9302     mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
9303     mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
9304                           AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
9305     mWindow->assertNoEvents();
9306 }
9307 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher)9308 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
9309     GTEST_SKIP() << "Flaky test (b/270393106)";
9310     sendAndConsumeKeyDown(/*deviceId=*/1);
9311     for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9312         std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
9313         ASSERT_NE(nullptr, repeatEvent);
9314         EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
9315                   IdGenerator::getSource(repeatEvent->getId()));
9316     }
9317 }
9318 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_RepeatKeyEventsUseUniqueEventId)9319 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
9320     GTEST_SKIP() << "Flaky test (b/270393106)";
9321     sendAndConsumeKeyDown(/*deviceId=*/1);
9322 
9323     std::unordered_set<int32_t> idSet;
9324     for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9325         std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
9326         ASSERT_NE(nullptr, repeatEvent);
9327         int32_t id = repeatEvent->getId();
9328         EXPECT_EQ(idSet.end(), idSet.find(id));
9329         idSet.insert(id);
9330     }
9331 }
9332 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat)9333 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
9334     injectKeyRepeat(0);
9335     mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
9336     for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
9337         expectKeyRepeatOnce(repeatCount);
9338     }
9339     injectKeyRepeat(1);
9340     // Expect repeatCount to be 3 instead of 1
9341     expectKeyRepeatOnce(3);
9342 }
9343 
TEST_F(InputDispatcherKeyRepeatTest,FocusedWindow_NoRepeatWhenKeyRepeatDisabled)9344 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_NoRepeatWhenKeyRepeatDisabled) {
9345     SCOPED_FLAG_OVERRIDE(keyboard_repeat_keys, true);
9346     static constexpr std::chrono::milliseconds KEY_NO_REPEAT_ASSERTION_TIMEOUT = 100ms;
9347 
9348     mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY,
9349                                            /*repeatKeyEnabled=*/false);
9350     sendAndConsumeKeyDown(/*deviceId=*/1);
9351 
9352     ASSERT_GT(KEY_NO_REPEAT_ASSERTION_TIMEOUT, KEY_REPEAT_TIMEOUT)
9353             << "Ensure the check for no key repeats extends beyond the repeat timeout duration.";
9354     ASSERT_GT(KEY_NO_REPEAT_ASSERTION_TIMEOUT, KEY_REPEAT_DELAY)
9355             << "Ensure the check for no key repeats extends beyond the repeat delay duration.";
9356 
9357     // No events should be returned if key repeat is turned off.
9358     // Wait for KEY_NO_REPEAT_ASSERTION_TIMEOUT to return no events to ensure key repeat disabled.
9359     mWindow->assertNoEvents(KEY_NO_REPEAT_ASSERTION_TIMEOUT);
9360 }
9361 
9362 /* Test InputDispatcher for MultiDisplay */
9363 class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
9364 public:
SetUp()9365     virtual void SetUp() override {
9366         InputDispatcherTest::SetUp();
9367 
9368         application1 = std::make_shared<FakeApplicationHandle>();
9369         windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
9370                                                      ui::LogicalDisplayId::DEFAULT);
9371 
9372         // Set focus window for primary display, but focused display would be second one.
9373         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
9374         windowInPrimary->setFocusable(true);
9375         mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
9376 
9377         setFocusedWindow(windowInPrimary);
9378         windowInPrimary->consumeFocusEvent(true);
9379 
9380         application2 = std::make_shared<FakeApplicationHandle>();
9381         windowInSecondary =
9382                 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
9383         // Set focus to second display window.
9384         // Set focus display to second one.
9385         mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
9386         mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
9387 
9388         // Set focus window for second display.
9389         mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
9390         windowInSecondary->setFocusable(true);
9391         mDispatcher->onWindowInfosChanged(
9392                 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
9393         setFocusedWindow(windowInSecondary);
9394         windowInSecondary->consumeFocusEvent(true);
9395     }
9396 
TearDown()9397     virtual void TearDown() override {
9398         InputDispatcherTest::TearDown();
9399 
9400         application1.reset();
9401         windowInPrimary.clear();
9402         application2.reset();
9403         windowInSecondary.clear();
9404     }
9405 
9406 protected:
9407     std::shared_ptr<FakeApplicationHandle> application1;
9408     sp<FakeWindowHandle> windowInPrimary;
9409     std::shared_ptr<FakeApplicationHandle> application2;
9410     sp<FakeWindowHandle> windowInSecondary;
9411 };
9412 
TEST_F(InputDispatcherFocusOnTwoDisplaysTest,SetInputWindow_MultiDisplayTouch)9413 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
9414     // Test touch down on primary display.
9415     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9416               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9417                                ui::LogicalDisplayId::DEFAULT))
9418             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9419     windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9420     windowInSecondary->assertNoEvents();
9421 
9422     // Test touch down on second display.
9423     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9424               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
9425             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9426     windowInPrimary->assertNoEvents();
9427     windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
9428 }
9429 
TEST_F(InputDispatcherFocusOnTwoDisplaysTest,SetInputWindow_MultiDisplayFocus)9430 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
9431     // Test inject a key down with display id specified.
9432     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9433               injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
9434             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9435     windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
9436     windowInSecondary->assertNoEvents();
9437 
9438     // Test inject a key down without display id specified.
9439     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
9440             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9441     windowInPrimary->assertNoEvents();
9442     windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
9443 
9444     // Remove all windows in secondary display.
9445     mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
9446 
9447     // Old focus should receive a cancel event.
9448     windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
9449 
9450     // Test inject a key down, should timeout because of no target window.
9451     ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
9452     windowInPrimary->assertNoEvents();
9453     windowInSecondary->consumeFocusEvent(false);
9454     windowInSecondary->assertNoEvents();
9455 }
9456 
9457 // Test per-display input monitors for motion event.
TEST_F(InputDispatcherFocusOnTwoDisplaysTest,MonitorMotionEvent_MultiDisplay)9458 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
9459     FakeMonitorReceiver monitorInPrimary =
9460             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
9461     FakeMonitorReceiver monitorInSecondary =
9462             FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
9463 
9464     // Test touch down on primary display.
9465     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9466               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9467                                ui::LogicalDisplayId::DEFAULT))
9468             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9469     windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9470     monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9471     windowInSecondary->assertNoEvents();
9472     monitorInSecondary.assertNoEvents();
9473 
9474     // Test touch down on second display.
9475     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9476               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
9477             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9478     windowInPrimary->assertNoEvents();
9479     monitorInPrimary.assertNoEvents();
9480     windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
9481     monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
9482 
9483     // Lift up the touch from the second display
9484     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9485               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
9486             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9487     windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
9488     monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
9489 
9490     // Test inject a non-pointer motion event.
9491     // If specific a display, it will dispatch to the focused window of particular display,
9492     // or it will dispatch to the focused window of focused display.
9493     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9494               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
9495                                ui::LogicalDisplayId::INVALID))
9496             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9497     windowInPrimary->assertNoEvents();
9498     monitorInPrimary.assertNoEvents();
9499     windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
9500     monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
9501 }
9502 
9503 // Test per-display input monitors for key event.
TEST_F(InputDispatcherFocusOnTwoDisplaysTest,MonitorKeyEvent_MultiDisplay)9504 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
9505     // Input monitor per display.
9506     FakeMonitorReceiver monitorInPrimary =
9507             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
9508     FakeMonitorReceiver monitorInSecondary =
9509             FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
9510 
9511     // Test inject a key down.
9512     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
9513             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9514     windowInPrimary->assertNoEvents();
9515     monitorInPrimary.assertNoEvents();
9516     windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
9517     monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
9518 }
9519 
TEST_F(InputDispatcherFocusOnTwoDisplaysTest,CanFocusWindowOnUnfocusedDisplay)9520 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
9521     sp<FakeWindowHandle> secondWindowInPrimary =
9522             sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
9523                                        ui::LogicalDisplayId::DEFAULT);
9524     secondWindowInPrimary->setFocusable(true);
9525     mDispatcher->onWindowInfosChanged(
9526             {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
9527               *windowInSecondary->getInfo()},
9528              {},
9529              0,
9530              0});
9531     setFocusedWindow(secondWindowInPrimary);
9532     windowInPrimary->consumeFocusEvent(false);
9533     secondWindowInPrimary->consumeFocusEvent(true);
9534 
9535     // Test inject a key down.
9536     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9537               injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
9538             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9539     windowInPrimary->assertNoEvents();
9540     windowInSecondary->assertNoEvents();
9541     secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
9542 }
9543 
TEST_F(InputDispatcherFocusOnTwoDisplaysTest,CancelTouch_MultiDisplay)9544 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
9545     FakeMonitorReceiver monitorInPrimary =
9546             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
9547     FakeMonitorReceiver monitorInSecondary =
9548             FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
9549 
9550     // Test touch down on primary display.
9551     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9552               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9553                                ui::LogicalDisplayId::DEFAULT))
9554             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9555     windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9556     monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9557 
9558     // Test touch down on second display.
9559     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9560               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
9561             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9562     windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
9563     monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
9564 
9565     // Trigger cancel touch.
9566     mDispatcher->cancelCurrentTouch();
9567     windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
9568     monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
9569     windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
9570     monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
9571 
9572     // Test inject a move motion event, no window/monitor should receive the event.
9573     ASSERT_EQ(InputEventInjectionResult::FAILED,
9574               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9575                                 ui::LogicalDisplayId::DEFAULT, {110, 200}))
9576             << "Inject motion event should return InputEventInjectionResult::FAILED";
9577     windowInPrimary->assertNoEvents();
9578     monitorInPrimary.assertNoEvents();
9579 
9580     ASSERT_EQ(InputEventInjectionResult::FAILED,
9581               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9582                                 SECOND_DISPLAY_ID, {110, 200}))
9583             << "Inject motion event should return InputEventInjectionResult::FAILED";
9584     windowInSecondary->assertNoEvents();
9585     monitorInSecondary.assertNoEvents();
9586 }
9587 
9588 /**
9589  * Send a key to the primary display and to the secondary display.
9590  * Then cause the key on the primary display to be canceled by sending in a stale key.
9591  * Ensure that the key on the primary display is canceled, and that the key on the secondary display
9592  * does not get canceled.
9593  */
TEST_F(InputDispatcherFocusOnTwoDisplaysTest,WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture)9594 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
9595     // Send a key down on primary display
9596     mDispatcher->notifyKey(
9597             KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9598                     .displayId(ui::LogicalDisplayId::DEFAULT)
9599                     .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9600                     .build());
9601     windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
9602                                            WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
9603     windowInSecondary->assertNoEvents();
9604 
9605     // Send a key down on second display
9606     mDispatcher->notifyKey(
9607             KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9608                     .displayId(SECOND_DISPLAY_ID)
9609                     .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9610                     .build());
9611     windowInSecondary->consumeKeyEvent(
9612             AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9613     windowInPrimary->assertNoEvents();
9614 
9615     // Send a valid key up event on primary display that will be dropped because it is stale
9616     NotifyKeyArgs staleKeyUp =
9617             KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
9618                     .displayId(ui::LogicalDisplayId::DEFAULT)
9619                     .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9620                     .build();
9621     static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9622     mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9623     std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9624     mDispatcher->notifyKey(staleKeyUp);
9625 
9626     // Only the key gesture corresponding to the dropped event should receive the cancel event.
9627     // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
9628     // receive any events.
9629     windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
9630                                            WithDisplayId(ui::LogicalDisplayId::DEFAULT),
9631                                            WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9632     windowInSecondary->assertNoEvents();
9633 }
9634 
9635 /**
9636  * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
9637  */
TEST_F(InputDispatcherFocusOnTwoDisplaysTest,WhenDropMotionEvent_OnlyCancelCorrespondingGesture)9638 TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
9639     // Send touch down on primary display.
9640     mDispatcher->notifyMotion(
9641             MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9642                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9643                     .displayId(ui::LogicalDisplayId::DEFAULT)
9644                     .build());
9645     windowInPrimary->consumeMotionEvent(
9646             AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
9647     windowInSecondary->assertNoEvents();
9648 
9649     // Send touch down on second display.
9650     mDispatcher->notifyMotion(
9651             MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9652                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9653                     .displayId(SECOND_DISPLAY_ID)
9654                     .build());
9655     windowInPrimary->assertNoEvents();
9656     windowInSecondary->consumeMotionEvent(
9657             AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9658 
9659     // inject a valid MotionEvent on primary display that will be stale when it arrives.
9660     NotifyMotionArgs staleMotionUp =
9661             MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9662                     .displayId(ui::LogicalDisplayId::DEFAULT)
9663                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9664                     .build();
9665     static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9666     mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9667     std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9668     mDispatcher->notifyMotion(staleMotionUp);
9669 
9670     // For stale motion events, we let the gesture to complete. This behaviour is different from key
9671     // events, where we would cancel the current keys instead.
9672     windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
9673     windowInSecondary->assertNoEvents();
9674 }
9675 
9676 class InputFilterTest : public InputDispatcherTest {
9677 protected:
testNotifyMotion(ui::LogicalDisplayId displayId,bool expectToBeFiltered,const ui::Transform & transform=ui::Transform ())9678     void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
9679                           const ui::Transform& transform = ui::Transform()) {
9680         NotifyMotionArgs motionArgs;
9681 
9682         motionArgs =
9683                 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
9684         mDispatcher->notifyMotion(motionArgs);
9685         motionArgs =
9686                 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
9687         mDispatcher->notifyMotion(motionArgs);
9688         ASSERT_TRUE(mDispatcher->waitForIdle());
9689         if (expectToBeFiltered) {
9690             const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
9691             mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
9692         } else {
9693             mFakePolicy->assertFilterInputEventWasNotCalled();
9694         }
9695     }
9696 
testNotifyKey(bool expectToBeFiltered)9697     void testNotifyKey(bool expectToBeFiltered) {
9698         NotifyKeyArgs keyArgs;
9699 
9700         keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
9701         mDispatcher->notifyKey(keyArgs);
9702         keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
9703         mDispatcher->notifyKey(keyArgs);
9704         ASSERT_TRUE(mDispatcher->waitForIdle());
9705 
9706         if (expectToBeFiltered) {
9707             mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
9708         } else {
9709             mFakePolicy->assertFilterInputEventWasNotCalled();
9710         }
9711     }
9712 };
9713 
9714 // Test InputFilter for MotionEvent
TEST_F(InputFilterTest,MotionEvent_InputFilter)9715 TEST_F(InputFilterTest, MotionEvent_InputFilter) {
9716     // Since the InputFilter is disabled by default, check if touch events aren't filtered.
9717     testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
9718     testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
9719 
9720     // Enable InputFilter
9721     mDispatcher->setInputFilterEnabled(true);
9722     // Test touch on both primary and second display, and check if both events are filtered.
9723     testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
9724     testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
9725 
9726     // Disable InputFilter
9727     mDispatcher->setInputFilterEnabled(false);
9728     // Test touch on both primary and second display, and check if both events aren't filtered.
9729     testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
9730     testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
9731 }
9732 
9733 // Test InputFilter for KeyEvent
TEST_F(InputFilterTest,KeyEvent_InputFilter)9734 TEST_F(InputFilterTest, KeyEvent_InputFilter) {
9735     // Since the InputFilter is disabled by default, check if key event aren't filtered.
9736     testNotifyKey(/*expectToBeFiltered=*/false);
9737 
9738     // Enable InputFilter
9739     mDispatcher->setInputFilterEnabled(true);
9740     // Send a key event, and check if it is filtered.
9741     testNotifyKey(/*expectToBeFiltered=*/true);
9742 
9743     // Disable InputFilter
9744     mDispatcher->setInputFilterEnabled(false);
9745     // Send a key event, and check if it isn't filtered.
9746     testNotifyKey(/*expectToBeFiltered=*/false);
9747 }
9748 
9749 // Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
9750 // logical display coordinate space.
TEST_F(InputFilterTest,MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion)9751 TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
9752     ui::Transform firstDisplayTransform;
9753     firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
9754     ui::Transform secondDisplayTransform;
9755     secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
9756 
9757     std::vector<gui::DisplayInfo> displayInfos(2);
9758     displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
9759     displayInfos[0].transform = firstDisplayTransform;
9760     displayInfos[1].displayId = SECOND_DISPLAY_ID;
9761     displayInfos[1].transform = secondDisplayTransform;
9762 
9763     mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
9764 
9765     // Enable InputFilter
9766     mDispatcher->setInputFilterEnabled(true);
9767 
9768     // Ensure the correct transforms are used for the displays.
9769     testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
9770                      firstDisplayTransform);
9771     testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
9772 }
9773 
9774 class InputFilterInjectionPolicyTest : public InputDispatcherTest {
9775 protected:
SetUp()9776     virtual void SetUp() override {
9777         InputDispatcherTest::SetUp();
9778 
9779         /**
9780          * We don't need to enable input filter to test the injected event policy, but we enabled it
9781          * here to make the tests more realistic, since this policy only matters when inputfilter is
9782          * on.
9783          */
9784         mDispatcher->setInputFilterEnabled(true);
9785 
9786         std::shared_ptr<InputApplicationHandle> application =
9787                 std::make_shared<FakeApplicationHandle>();
9788         mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
9789                                              ui::LogicalDisplayId::DEFAULT);
9790 
9791         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
9792         mWindow->setFocusable(true);
9793         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9794         setFocusedWindow(mWindow);
9795         mWindow->consumeFocusEvent(true);
9796     }
9797 
testInjectedKey(int32_t policyFlags,int32_t injectedDeviceId,int32_t resolvedDeviceId,int32_t flags)9798     void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9799                          int32_t flags) {
9800         KeyEvent event;
9801 
9802         const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9803         event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
9804                          ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9805                          AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
9806         const int32_t additionalPolicyFlags =
9807                 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9808         ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9809                   mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
9810                                                 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
9811                                                 policyFlags | additionalPolicyFlags));
9812 
9813         mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
9814     }
9815 
testInjectedMotion(int32_t policyFlags,int32_t injectedDeviceId,int32_t resolvedDeviceId,int32_t flags)9816     void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9817                             int32_t flags) {
9818         MotionEvent event;
9819         PointerProperties pointerProperties[1];
9820         PointerCoords pointerCoords[1];
9821         pointerProperties[0].clear();
9822         pointerProperties[0].id = 0;
9823         pointerCoords[0].clear();
9824         pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9825         pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9826 
9827         ui::Transform identityTransform;
9828         const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9829         event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9830                          DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9831                          AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9832                          identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
9833                          AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
9834                          eventTime,
9835                          /*pointerCount=*/1, pointerProperties, pointerCoords);
9836 
9837         const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9838         ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9839                   mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
9840                                                 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
9841                                                 policyFlags | additionalPolicyFlags));
9842 
9843         mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
9844     }
9845 
9846 private:
9847     sp<FakeWindowHandle> mWindow;
9848 };
9849 
TEST_F(InputFilterInjectionPolicyTest,TrustedFilteredEvents_KeepOriginalDeviceId)9850 TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
9851     // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9852     // filter. Without it, the event will no different from a regularly injected event, and the
9853     // injected device id will be overwritten.
9854     testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9855                     /*flags=*/0);
9856 }
9857 
TEST_F(InputFilterInjectionPolicyTest,KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag)9858 TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9859     testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
9860                     /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9861                     AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9862 }
9863 
TEST_F(InputFilterInjectionPolicyTest,MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag)9864 TEST_F(InputFilterInjectionPolicyTest,
9865        MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9866     testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
9867                        /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9868                        AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9869 }
9870 
TEST_F(InputFilterInjectionPolicyTest,RegularInjectedEvents_ReceiveVirtualDeviceId)9871 TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
9872     testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9873                     /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
9874 }
9875 
9876 class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9877 protected:
SetUp()9878     virtual void SetUp() override {
9879         InputDispatcherTest::SetUp();
9880 
9881         std::shared_ptr<FakeApplicationHandle> application =
9882                 std::make_shared<FakeApplicationHandle>();
9883         application->setDispatchingTimeout(100ms);
9884         mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
9885                                              ui::LogicalDisplayId::DEFAULT);
9886         mWindow->setFrame(Rect(0, 0, 100, 100));
9887         mWindow->setDispatchingTimeout(100ms);
9888         mWindow->setFocusable(true);
9889 
9890         // Set focused application.
9891         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
9892 
9893         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9894         setFocusedWindow(mWindow);
9895         mWindow->consumeFocusEvent(true);
9896     }
9897 
notifyAndConsumeMotion(int32_t action,uint32_t source,ui::LogicalDisplayId displayId,nsecs_t eventTime)9898     void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
9899                                 nsecs_t eventTime) {
9900         mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9901                                           .displayId(displayId)
9902                                           .eventTime(eventTime)
9903                                           .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9904                                           .build());
9905         mWindow->consumeMotionEvent(WithMotionAction(action));
9906     }
9907 
9908 private:
9909     sp<FakeWindowHandle> mWindow;
9910 };
9911 
TEST_F_WITH_FLAGS(InputDispatcherUserActivityPokeTests,MinPokeTimeObserved,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (com::android::input::flags,rate_limit_user_activity_poke_in_dispatcher)))9912 TEST_F_WITH_FLAGS(
9913         InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9914         REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9915                                             rate_limit_user_activity_poke_in_dispatcher))) {
9916     mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9917 
9918     // First event of type TOUCH. Should poke.
9919     notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9920                            milliseconds_to_nanoseconds(50));
9921     mFakePolicy->assertUserActivityPoked(
9922             {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9923               ui::LogicalDisplayId::DEFAULT}});
9924 
9925     // 80ns > 50ns has passed since previous TOUCH event. Should poke.
9926     notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9927                            milliseconds_to_nanoseconds(130));
9928     mFakePolicy->assertUserActivityPoked(
9929             {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9930               ui::LogicalDisplayId::DEFAULT}});
9931 
9932     // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
9933     notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9934                            ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
9935     mFakePolicy->assertUserActivityPoked(
9936             {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9937               ui::LogicalDisplayId::DEFAULT}});
9938 
9939     // Within 50ns of previous TOUCH event. Should NOT poke.
9940     notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9941                            milliseconds_to_nanoseconds(140));
9942     mFakePolicy->assertUserActivityNotPoked();
9943 
9944     // Within 50ns of previous OTHER event. Should NOT poke.
9945     notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9946                            ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
9947     mFakePolicy->assertUserActivityNotPoked();
9948 
9949     // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9950     // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
9951     notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
9952                            milliseconds_to_nanoseconds(160));
9953     mFakePolicy->assertUserActivityNotPoked();
9954 
9955     // 65ns > 50ns has passed since previous OTHER event. Should poke.
9956     notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9957                            ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
9958     mFakePolicy->assertUserActivityPoked(
9959             {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9960               ui::LogicalDisplayId::DEFAULT}});
9961 
9962     // 170ns > 50ns has passed since previous TOUCH event. Should poke.
9963     notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
9964                            milliseconds_to_nanoseconds(300));
9965     mFakePolicy->assertUserActivityPoked(
9966             {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9967               ui::LogicalDisplayId::DEFAULT}});
9968 
9969     // Assert that there's no more user activity poke event.
9970     mFakePolicy->assertUserActivityNotPoked();
9971 }
9972 
TEST_F_WITH_FLAGS(InputDispatcherUserActivityPokeTests,DefaultMinPokeTimeOf100MsUsed,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (com::android::input::flags,rate_limit_user_activity_poke_in_dispatcher)))9973 TEST_F_WITH_FLAGS(
9974         InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9975         REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9976                                             rate_limit_user_activity_poke_in_dispatcher))) {
9977     notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9978                            milliseconds_to_nanoseconds(200));
9979     mFakePolicy->assertUserActivityPoked(
9980             {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9981               ui::LogicalDisplayId::DEFAULT}});
9982 
9983     notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9984                            milliseconds_to_nanoseconds(280));
9985     mFakePolicy->assertUserActivityNotPoked();
9986 
9987     notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9988                            milliseconds_to_nanoseconds(340));
9989     mFakePolicy->assertUserActivityPoked(
9990             {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9991               ui::LogicalDisplayId::DEFAULT}});
9992 }
9993 
TEST_F_WITH_FLAGS(InputDispatcherUserActivityPokeTests,ZeroMinPokeTimeDisablesRateLimiting,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (com::android::input::flags,rate_limit_user_activity_poke_in_dispatcher)))9994 TEST_F_WITH_FLAGS(
9995         InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9996         REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9997                                             rate_limit_user_activity_poke_in_dispatcher))) {
9998     mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9999 
10000     notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
10001                            20);
10002     mFakePolicy->assertUserActivityPoked();
10003 
10004     notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
10005                            30);
10006     mFakePolicy->assertUserActivityPoked();
10007 }
10008 
10009 class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
SetUp()10010     virtual void SetUp() override {
10011         InputDispatcherTest::SetUp();
10012 
10013         std::shared_ptr<FakeApplicationHandle> application =
10014                 std::make_shared<FakeApplicationHandle>();
10015         mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
10016                                                       ui::LogicalDisplayId::DEFAULT);
10017         mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
10018 
10019         mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
10020                                                     ui::LogicalDisplayId::DEFAULT);
10021         mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
10022 
10023         // Set focused application.
10024         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
10025         mFocusedWindow->setFocusable(true);
10026 
10027         // Expect one focus window exist in display.
10028         mDispatcher->onWindowInfosChanged(
10029                 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
10030         setFocusedWindow(mFocusedWindow);
10031         mFocusedWindow->consumeFocusEvent(true);
10032     }
10033 
TearDown()10034     virtual void TearDown() override {
10035         InputDispatcherTest::TearDown();
10036 
10037         mUnfocusedWindow.clear();
10038         mFocusedWindow.clear();
10039     }
10040 
10041 protected:
10042     sp<FakeWindowHandle> mUnfocusedWindow;
10043     sp<FakeWindowHandle> mFocusedWindow;
10044     static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
10045 };
10046 
10047 // Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
10048 // DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
10049 // the onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus,OnPointerDownOutsideFocus_Success)10050 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
10051     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10052               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10053                                ui::LogicalDisplayId::DEFAULT, {20, 20}))
10054             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10055     mUnfocusedWindow->consumeMotionDown();
10056 
10057     ASSERT_TRUE(mDispatcher->waitForIdle());
10058     mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
10059 }
10060 
10061 // Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
10062 // DOWN on the window that doesn't have focus. Ensure no window received the
10063 // onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus,OnPointerDownOutsideFocus_NonPointerSource)10064 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
10065     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10066               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
10067                                {20, 20}))
10068             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10069     mFocusedWindow->consumeMotionDown();
10070 
10071     ASSERT_TRUE(mDispatcher->waitForIdle());
10072     mFakePolicy->assertOnPointerDownWasNotCalled();
10073 }
10074 
10075 // Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
10076 // have focus. Ensure no window received the onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus,OnPointerDownOutsideFocus_NonMotionFailure)10077 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
10078     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10079               injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
10080             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10081     mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
10082 
10083     ASSERT_TRUE(mDispatcher->waitForIdle());
10084     mFakePolicy->assertOnPointerDownWasNotCalled();
10085 }
10086 
10087 // Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
10088 // DOWN on the window that already has focus. Ensure no window received the
10089 // onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus,OnPointerDownOutsideFocus_OnAlreadyFocusedWindow)10090 TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
10091     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10092               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10093                                ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
10094             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10095     mFocusedWindow->consumeMotionDown();
10096 
10097     ASSERT_TRUE(mDispatcher->waitForIdle());
10098     mFakePolicy->assertOnPointerDownWasNotCalled();
10099 }
10100 
10101 // Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
10102 // NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus,NoFocusChangeFlag)10103 TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
10104     const MotionEvent event =
10105             MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
10106                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10107                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
10108                     .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
10109                     .build();
10110     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
10111             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10112     mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
10113                                            AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
10114 
10115     ASSERT_TRUE(mDispatcher->waitForIdle());
10116     mFakePolicy->assertOnPointerDownWasNotCalled();
10117     // Ensure that the unfocused window did not receive any FOCUS events.
10118     mUnfocusedWindow->assertNoEvents();
10119 }
10120 
10121 // These tests ensures we can send touch events to a single client when there are multiple input
10122 // windows that point to the same client token.
10123 class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
SetUp()10124     virtual void SetUp() override {
10125         InputDispatcherTest::SetUp();
10126 
10127         std::shared_ptr<FakeApplicationHandle> application =
10128                 std::make_shared<FakeApplicationHandle>();
10129         mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
10130                                               ui::LogicalDisplayId::DEFAULT);
10131         mWindow1->setFrame(Rect(0, 0, 100, 100));
10132 
10133         mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
10134         mWindow2->setFrame(Rect(100, 100, 200, 200));
10135 
10136         mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10137     }
10138 
10139 protected:
10140     sp<FakeWindowHandle> mWindow1;
10141     sp<FakeWindowHandle> mWindow2;
10142 
10143     // Helper function to convert the point from screen coordinates into the window's space
getPointInWindow(const WindowInfo * windowInfo,const PointF & point)10144     static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
10145         vec2 vals = windowInfo->transform.transform(point.x, point.y);
10146         return {vals.x, vals.y};
10147     }
10148 
consumeMotionEvent(const sp<FakeWindowHandle> & window,int32_t expectedAction,const std::vector<PointF> & points)10149     void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
10150                             const std::vector<PointF>& points) {
10151         const std::string name = window->getName();
10152         std::unique_ptr<MotionEvent> motionEvent =
10153                 window->consumeMotionEvent(WithMotionAction(expectedAction));
10154         ASSERT_NE(nullptr, motionEvent);
10155         ASSERT_EQ(points.size(), motionEvent->getPointerCount());
10156 
10157         for (size_t i = 0; i < points.size(); i++) {
10158             float expectedX = points[i].x;
10159             float expectedY = points[i].y;
10160 
10161             EXPECT_EQ(expectedX, motionEvent->getX(i))
10162                     << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
10163                     << ", got " << motionEvent->getX(i);
10164             EXPECT_EQ(expectedY, motionEvent->getY(i))
10165                     << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
10166                     << ", got " << motionEvent->getY(i);
10167         }
10168     }
10169 
touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow,int32_t action,const std::vector<PointF> & touchedPoints,std::vector<PointF> expectedPoints)10170     void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
10171                                  const std::vector<PointF>& touchedPoints,
10172                                  std::vector<PointF> expectedPoints) {
10173         mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
10174                                                      ui::LogicalDisplayId::DEFAULT, touchedPoints));
10175 
10176         consumeMotionEvent(touchedWindow, action, expectedPoints);
10177     }
10178 };
10179 
TEST_F(InputDispatcherMultiWindowSameTokenTests,SingleTouchSameScale)10180 TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
10181     // Touch Window 1
10182     PointF touchedPoint = {10, 10};
10183     PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
10184     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
10185 
10186     // Release touch on Window 1
10187     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
10188 
10189     // Touch Window 2
10190     touchedPoint = {150, 150};
10191     expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
10192     touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
10193 }
10194 
TEST_F(InputDispatcherMultiWindowSameTokenTests,SingleTouchDifferentTransform)10195 TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
10196     // Set scale value for window2
10197     mWindow2->setWindowScale(0.5f, 0.5f);
10198     mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10199 
10200     // Touch Window 1
10201     PointF touchedPoint = {10, 10};
10202     PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
10203     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
10204     // Release touch on Window 1
10205     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
10206 
10207     // Touch Window 2
10208     touchedPoint = {150, 150};
10209     expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
10210     touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
10211     touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
10212 
10213     // Update the transform so rotation is set
10214     mWindow2->setWindowTransform(0, -1, 1, 0);
10215     mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10216     expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
10217     touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
10218 }
10219 
TEST_F(InputDispatcherMultiWindowSameTokenTests,MultipleTouchDifferentTransform)10220 TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
10221     mWindow2->setWindowScale(0.5f, 0.5f);
10222     mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10223 
10224     // Touch Window 1
10225     std::vector<PointF> touchedPoints = {PointF{10, 10}};
10226     std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
10227     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
10228 
10229     // Touch Window 2
10230     // Since this is part of the same touch gesture that has already been dispatched to Window 1,
10231     // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
10232     // will continue to be dispatched through Window 1.
10233     touchedPoints.push_back(PointF{150, 150});
10234     expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
10235     touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
10236 
10237     // Release Window 2
10238     touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
10239     expectedPoints.pop_back();
10240 
10241     // Update the transform so rotation is set for Window 2
10242     mWindow2->setWindowTransform(0, -1, 1, 0);
10243     mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10244     expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
10245     touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
10246 }
10247 
TEST_F(InputDispatcherMultiWindowSameTokenTests,MultipleTouchMoveDifferentTransform)10248 TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
10249     mWindow2->setWindowScale(0.5f, 0.5f);
10250     mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10251 
10252     // Touch Window 1
10253     std::vector<PointF> touchedPoints = {PointF{10, 10}};
10254     std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
10255     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
10256 
10257     // Touch Window 2
10258     touchedPoints.push_back(PointF{150, 150});
10259     expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
10260 
10261     touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
10262 
10263     // Move both windows
10264     touchedPoints = {{20, 20}, {175, 175}};
10265     expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10266                       getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10267 
10268     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
10269 
10270     // Release Window 2
10271     touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
10272     expectedPoints.pop_back();
10273 
10274     // Touch Window 2
10275     mWindow2->setWindowTransform(0, -1, 1, 0);
10276     mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10277     expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
10278     touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
10279 
10280     // Move both windows
10281     touchedPoints = {{20, 20}, {175, 175}};
10282     expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10283                       getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10284 
10285     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
10286 }
10287 
TEST_F(InputDispatcherMultiWindowSameTokenTests,MultipleWindowsFirstTouchWithScale)10288 TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
10289     mWindow1->setWindowScale(0.5f, 0.5f);
10290     mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10291 
10292     // Touch Window 1
10293     std::vector<PointF> touchedPoints = {PointF{10, 10}};
10294     std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
10295     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
10296 
10297     // Touch Window 2
10298     touchedPoints.push_back(PointF{150, 150});
10299     expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
10300 
10301     touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
10302 
10303     // Move both windows
10304     touchedPoints = {{20, 20}, {175, 175}};
10305     expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10306                       getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10307 
10308     touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
10309 }
10310 
10311 /**
10312  * When one of the windows is slippery, the touch should not slip into the other window with the
10313  * same input channel.
10314  */
TEST_F(InputDispatcherMultiWindowSameTokenTests,TouchDoesNotSlipEvenIfSlippery)10315 TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
10316     mWindow1->setSlippery(true);
10317     mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10318 
10319     // Touch down in window 1
10320     mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10321                                                  ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
10322     consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
10323 
10324     // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
10325     // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
10326     // getting generated.
10327     mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
10328                                                  ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
10329 
10330     consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
10331 }
10332 
10333 /**
10334  * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
10335  * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
10336  * that the pointer is hovering over may have a different transform.
10337  */
TEST_F(InputDispatcherMultiWindowSameTokenTests,HoverIntoClone)10338 TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
10339     mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
10340 
10341     // Start hover in window 1
10342     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
10343                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10344                                       .build());
10345     consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
10346                        {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
10347     // Move hover to window 2.
10348     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10349                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10350                                       .build());
10351     consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
10352     consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
10353                        {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
10354 }
10355 
10356 class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
SetUp()10357     virtual void SetUp() override {
10358         InputDispatcherTest::SetUp();
10359 
10360         mApplication = std::make_shared<FakeApplicationHandle>();
10361         mApplication->setDispatchingTimeout(100ms);
10362         mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
10363                                              ui::LogicalDisplayId::DEFAULT);
10364         mWindow->setFrame(Rect(0, 0, 30, 30));
10365         mWindow->setDispatchingTimeout(100ms);
10366         mWindow->setFocusable(true);
10367 
10368         // Set focused application.
10369         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
10370 
10371         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
10372         setFocusedWindow(mWindow);
10373         mWindow->consumeFocusEvent(true);
10374     }
10375 
TearDown()10376     virtual void TearDown() override {
10377         InputDispatcherTest::TearDown();
10378         mWindow.clear();
10379     }
10380 
10381 protected:
10382     static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
10383     std::shared_ptr<FakeApplicationHandle> mApplication;
10384     sp<FakeWindowHandle> mWindow;
10385     static constexpr PointF WINDOW_LOCATION = {20, 20};
10386 
tapOnWindow()10387     void tapOnWindow() {
10388         const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
10389                                              .x(WINDOW_LOCATION.x)
10390                                              .y(WINDOW_LOCATION.y);
10391         mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10392                                           .pointer(touchingPointer)
10393                                           .build());
10394         mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10395                                           .pointer(touchingPointer)
10396                                           .build());
10397     }
10398 
addSpyWindow()10399     sp<FakeWindowHandle> addSpyWindow() {
10400         sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
10401                                                               ui::LogicalDisplayId::DEFAULT);
10402         spy->setTrustedOverlay(true);
10403         spy->setFocusable(false);
10404         spy->setSpy(true);
10405         spy->setDispatchingTimeout(SPY_TIMEOUT);
10406         mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
10407         return spy;
10408     }
10409 };
10410 
10411 // Send a tap and respond, which should not cause an ANR.
TEST_F(InputDispatcherSingleWindowAnr,WhenTouchIsConsumed_NoAnr)10412 TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
10413     tapOnWindow();
10414     mWindow->consumeMotionDown();
10415     mWindow->consumeMotionUp();
10416     ASSERT_TRUE(mDispatcher->waitForIdle());
10417     mFakePolicy->assertNotifyAnrWasNotCalled();
10418 }
10419 
10420 // Send a regular key and respond, which should not cause an ANR.
TEST_F(InputDispatcherSingleWindowAnr,WhenKeyIsConsumed_NoAnr)10421 TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
10422     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
10423     mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
10424     ASSERT_TRUE(mDispatcher->waitForIdle());
10425     mFakePolicy->assertNotifyAnrWasNotCalled();
10426 }
10427 
TEST_F(InputDispatcherSingleWindowAnr,WhenFocusedApplicationChanges_NoAnr)10428 TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
10429     mWindow->setFocusable(false);
10430     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
10431     mWindow->consumeFocusEvent(false);
10432 
10433     InputEventInjectionResult result =
10434             injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10435                       ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
10436                       CONSUME_TIMEOUT_EVENT_EXPECTED,
10437                       /*allowKeyRepeat=*/false);
10438     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10439     // Key will not go to window because we have no focused window.
10440     // The 'no focused window' ANR timer should start instead.
10441 
10442     // Now, the focused application goes away.
10443     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
10444     // The key should get dropped and there should be no ANR.
10445 
10446     ASSERT_TRUE(mDispatcher->waitForIdle());
10447     mFakePolicy->assertNotifyAnrWasNotCalled();
10448 }
10449 
10450 // Send an event to the app and have the app not respond right away.
10451 // When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10452 // So InputDispatcher will enqueue ACTION_CANCEL event as well.
TEST_F(InputDispatcherSingleWindowAnr,OnPointerDown_BasicAnr)10453 TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
10454     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10455               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10456                                ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
10457 
10458     const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10459     ASSERT_TRUE(sequenceNum);
10460     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10461     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10462 
10463     mWindow->finishEvent(*sequenceNum);
10464     mWindow->consumeMotionEvent(
10465             AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
10466     ASSERT_TRUE(mDispatcher->waitForIdle());
10467     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10468 }
10469 
10470 // Send a key to the app and have the app not respond right away.
TEST_F(InputDispatcherSingleWindowAnr,OnKeyDown_BasicAnr)10471 TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
10472     // Inject a key, and don't respond - expect that ANR is called.
10473     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
10474     const auto [sequenceNum, _] = mWindow->receiveEvent();
10475     ASSERT_TRUE(sequenceNum);
10476     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10477     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10478     ASSERT_TRUE(mDispatcher->waitForIdle());
10479 }
10480 
10481 // We have a focused application, but no focused window
TEST_F(InputDispatcherSingleWindowAnr,FocusedApplication_NoFocusedWindow)10482 TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
10483     mWindow->setFocusable(false);
10484     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
10485     mWindow->consumeFocusEvent(false);
10486 
10487     // taps on the window work as normal
10488     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10489               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10490                                ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
10491     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10492     mDispatcher->waitForIdle();
10493     mFakePolicy->assertNotifyAnrWasNotCalled();
10494 
10495     // Once a focused event arrives, we get an ANR for this application
10496     // We specify the injection timeout to be smaller than the application timeout, to ensure that
10497     // injection times out (instead of failing).
10498     const InputEventInjectionResult result =
10499             injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10500                       ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
10501                       /*allowKeyRepeat=*/false);
10502     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
10503     const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10504     mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
10505     ASSERT_TRUE(mDispatcher->waitForIdle());
10506 }
10507 
10508 /**
10509  * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
10510  * there will not be an ANR.
10511  */
TEST_F(InputDispatcherSingleWindowAnr,StaleKeyEventDoesNotAnr)10512 TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
10513     mWindow->setFocusable(false);
10514     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
10515     mWindow->consumeFocusEvent(false);
10516 
10517     KeyEvent event;
10518     static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
10519     mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
10520     const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
10521             std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
10522 
10523     // Define a valid key down event that is stale (too old).
10524     event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
10525                      ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
10526                      /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
10527                      eventTime);
10528 
10529     const int32_t policyFlags =
10530             POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
10531 
10532     InputEventInjectionResult result =
10533             mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
10534                                           InputEventInjectionSync::WAIT_FOR_RESULT,
10535                                           INJECT_EVENT_TIMEOUT, policyFlags);
10536     ASSERT_EQ(InputEventInjectionResult::FAILED, result)
10537             << "Injection should fail because the event is stale";
10538 
10539     ASSERT_TRUE(mDispatcher->waitForIdle());
10540     mFakePolicy->assertNotifyAnrWasNotCalled();
10541     mWindow->assertNoEvents();
10542 }
10543 
10544 // We have a focused application, but no focused window
10545 // Make sure that we don't notify policy twice about the same ANR.
TEST_F(InputDispatcherSingleWindowAnr,NoFocusedWindow_DoesNotSendDuplicateAnr)10546 TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
10547     const std::chrono::duration appTimeout = 400ms;
10548     mApplication->setDispatchingTimeout(appTimeout);
10549     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
10550 
10551     mWindow->setFocusable(false);
10552     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
10553     mWindow->consumeFocusEvent(false);
10554 
10555     // Once a focused event arrives, we get an ANR for this application
10556     // We specify the injection timeout to be smaller than the application timeout, to ensure that
10557     // injection times out (instead of failing).
10558     const std::chrono::duration eventInjectionTimeout = 100ms;
10559     ASSERT_LT(eventInjectionTimeout, appTimeout);
10560     const InputEventInjectionResult result =
10561             injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10562                       ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
10563                       eventInjectionTimeout,
10564                       /*allowKeyRepeat=*/false);
10565     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
10566             << "result=" << ftl::enum_string(result);
10567     // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
10568     // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
10569     std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
10570     mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
10571 
10572     std::this_thread::sleep_for(appTimeout);
10573     // ANR should not be raised again. It is up to policy to do that if it desires.
10574     mFakePolicy->assertNotifyAnrWasNotCalled();
10575 
10576     // If we now get a focused window, the ANR should stop, but the policy handles that via
10577     // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
10578     ASSERT_TRUE(mDispatcher->waitForIdle());
10579 }
10580 
10581 // We have a focused application, but no focused window
TEST_F(InputDispatcherSingleWindowAnr,NoFocusedWindow_DropsFocusedEvents)10582 TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
10583     mWindow->setFocusable(false);
10584     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
10585     mWindow->consumeFocusEvent(false);
10586 
10587     // Once a focused event arrives, we get an ANR for this application
10588     ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
10589 
10590     const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10591     mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
10592 
10593     // Future focused events get dropped right away
10594     ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
10595     ASSERT_TRUE(mDispatcher->waitForIdle());
10596     mWindow->assertNoEvents();
10597 }
10598 
10599 /**
10600  * Ensure that the implementation is valid. Since we are using multiset to keep track of the
10601  * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
10602  * If we process 1 of the events, but ANR on the second event with the same timestamp,
10603  * the ANR mechanism should still work.
10604  *
10605  * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
10606  * DOWN event, while not responding on the second one.
10607  */
TEST_F(InputDispatcherSingleWindowAnr,Anr_HandlesEventsWithIdenticalTimestamps)10608 TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
10609     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
10610     injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10611                       ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
10612                       {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10613                        AMOTION_EVENT_INVALID_CURSOR_POSITION},
10614                       500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
10615 
10616     // Now send ACTION_UP, with identical timestamp
10617     injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10618                       ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
10619                       {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10620                        AMOTION_EVENT_INVALID_CURSOR_POSITION},
10621                       500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
10622 
10623     // We have now sent down and up. Let's consume first event and then ANR on the second.
10624     mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10625     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10626     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10627 }
10628 
10629 // A spy window can receive an ANR
TEST_F(InputDispatcherSingleWindowAnr,SpyWindowAnr)10630 TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
10631     sp<FakeWindowHandle> spy = addSpyWindow();
10632 
10633     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10634               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10635                                ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
10636     mWindow->consumeMotionDown();
10637 
10638     const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
10639     ASSERT_TRUE(sequenceNum);
10640     const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10641     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
10642 
10643     spy->finishEvent(*sequenceNum);
10644     spy->consumeMotionEvent(
10645             AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
10646     ASSERT_TRUE(mDispatcher->waitForIdle());
10647     mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
10648 }
10649 
10650 // If an app is not responding to a key event, spy windows should continue to receive
10651 // new motion events
TEST_F(InputDispatcherSingleWindowAnr,SpyWindowReceivesEventsDuringAppAnrOnKey)10652 TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
10653     sp<FakeWindowHandle> spy = addSpyWindow();
10654 
10655     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10656               injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
10657     mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
10658     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10659               injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
10660 
10661     // Stuck on the ACTION_UP
10662     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10663     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10664 
10665     // New tap will go to the spy window, but not to the window
10666     tapOnWindow();
10667     spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10668     spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
10669 
10670     mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
10671     mDispatcher->waitForIdle();
10672     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10673     mWindow->assertNoEvents();
10674     spy->assertNoEvents();
10675 }
10676 
10677 // If an app is not responding to a motion event, spy windows should continue to receive
10678 // new motion events
TEST_F(InputDispatcherSingleWindowAnr,SpyWindowReceivesEventsDuringAppAnrOnMotion)10679 TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
10680     sp<FakeWindowHandle> spy = addSpyWindow();
10681 
10682     tapOnWindow();
10683     spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10684     spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
10685 
10686     mWindow->consumeMotionDown();
10687     // Stuck on the ACTION_UP
10688     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10689     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10690 
10691     // New tap will go to the spy window, but not to the window
10692     tapOnWindow();
10693     spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10694     spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
10695 
10696     mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
10697     mDispatcher->waitForIdle();
10698     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10699     mWindow->assertNoEvents();
10700     spy->assertNoEvents();
10701 }
10702 
TEST_F(InputDispatcherSingleWindowAnr,UnresponsiveMonitorAnr)10703 TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
10704     mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
10705 
10706     FakeMonitorReceiver monitor =
10707             FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
10708 
10709     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10710               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10711                                ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
10712 
10713     mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10714     const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
10715     ASSERT_TRUE(consumeSeq);
10716 
10717     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
10718                                                          MONITOR_PID);
10719 
10720     monitor.finishEvent(*consumeSeq);
10721     monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
10722 
10723     ASSERT_TRUE(mDispatcher->waitForIdle());
10724     mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
10725 }
10726 
10727 // If a window is unresponsive, then you get anr. if the window later catches up and starts to
10728 // process events, you don't get an anr. When the window later becomes unresponsive again, you
10729 // get an ANR again.
10730 // 1. tap -> block on ACTION_UP -> receive ANR
10731 // 2. consume all pending events (= queue becomes healthy again)
10732 // 3. tap again -> block on ACTION_UP again -> receive ANR second time
TEST_F(InputDispatcherSingleWindowAnr,SameWindow_CanReceiveAnrTwice)10733 TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
10734     tapOnWindow();
10735 
10736     mWindow->consumeMotionDown();
10737     // Block on ACTION_UP
10738     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10739     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10740     mWindow->consumeMotionUp(); // Now the connection should be healthy again
10741     mDispatcher->waitForIdle();
10742     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10743     mWindow->assertNoEvents();
10744 
10745     tapOnWindow();
10746     mWindow->consumeMotionDown();
10747     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10748     mWindow->consumeMotionUp();
10749 
10750     mDispatcher->waitForIdle();
10751     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10752     mFakePolicy->assertNotifyAnrWasNotCalled();
10753     mWindow->assertNoEvents();
10754 }
10755 
10756 // If a connection remains unresponsive for a while, make sure policy is only notified once about
10757 // it.
TEST_F(InputDispatcherSingleWindowAnr,Policy_DoesNotGetDuplicateAnr)10758 TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
10759     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10760               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10761                                ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
10762 
10763     const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10764     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
10765     std::this_thread::sleep_for(windowTimeout);
10766     // 'notifyConnectionUnresponsive' should only be called once per connection
10767     mFakePolicy->assertNotifyAnrWasNotCalled();
10768     // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
10769     mWindow->consumeMotionDown();
10770     mWindow->consumeMotionEvent(
10771             AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
10772     mWindow->assertNoEvents();
10773     mDispatcher->waitForIdle();
10774     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10775     mFakePolicy->assertNotifyAnrWasNotCalled();
10776 }
10777 
10778 /**
10779  * If a window is processing a motion event, and then a key event comes in, the key event should
10780  * not get delivered to the focused window until the motion is processed.
10781  */
TEST_F(InputDispatcherSingleWindowAnr,Key_StaysPendingWhileMotionIsProcessed)10782 TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
10783     // The timeouts in this test are established by relying on the fact that the "key waiting for
10784     // events timeout" is equal to 500ms.
10785     ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
10786     mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
10787     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
10788 
10789     tapOnWindow();
10790     const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
10791     ASSERT_TRUE(downSequenceNum);
10792     const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
10793     ASSERT_TRUE(upSequenceNum);
10794 
10795     // Don't finish the events yet, and send a key
10796     mDispatcher->notifyKey(
10797             KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10798                     .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10799                     .build());
10800     // Key will not be sent to the window, yet, because the window is still processing events
10801     // and the key remains pending, waiting for the touch events to be processed
10802     // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
10803     mWindow->assertNoEvents(100ms);
10804 
10805     std::this_thread::sleep_for(400ms);
10806     // if we wait long enough though, dispatcher will give up, and still send the key
10807     // to the focused window, even though we have not yet finished the motion event
10808     mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
10809     mWindow->finishEvent(*downSequenceNum);
10810     mWindow->finishEvent(*upSequenceNum);
10811 }
10812 
10813 /**
10814  * If a window is processing a motion event, and then a key event comes in, the key event should
10815  * not go to the focused window until the motion is processed.
10816  * If then a new motion comes in, then the pending key event should be going to the currently
10817  * focused window right away.
10818  */
TEST_F(InputDispatcherSingleWindowAnr,PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn)10819 TEST_F(InputDispatcherSingleWindowAnr,
10820        PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10821     // The timeouts in this test are established by relying on the fact that the "key waiting for
10822     // events timeout" is equal to 500ms.
10823     ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
10824     mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
10825     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
10826 
10827     tapOnWindow();
10828     const auto& [downSequenceNum, _] = mWindow->receiveEvent();
10829     ASSERT_TRUE(downSequenceNum);
10830     const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
10831     ASSERT_TRUE(upSequenceNum);
10832     // Don't finish the events yet, and send a key
10833     mDispatcher->notifyKey(
10834             KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10835                     .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10836                     .build());
10837     // At this point, key is still pending, and should not be sent to the application yet.
10838     mWindow->assertNoEvents(100ms);
10839 
10840     // Now tap down again. It should cause the pending key to go to the focused window right away.
10841     tapOnWindow();
10842     // Now that we tapped, we should receive the key immediately.
10843     // Since there's still room for slowness, we use 200ms, which is much less than
10844     // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10845     std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10846     ASSERT_NE(nullptr, keyEvent);
10847     ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10848     ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10849     // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10850     // order.
10851     mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10852     mWindow->finishEvent(*upSequenceNum);   // first tap's ACTION_UP
10853     mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10854     mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
10855     mWindow->assertNoEvents();
10856 }
10857 
10858 /**
10859  * Send an event to the app and have the app not respond right away.
10860  * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10861  * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10862  * At some point, the window becomes responsive again.
10863  * Ensure that subsequent events get dropped, and the next gesture is delivered.
10864  */
TEST_F(InputDispatcherSingleWindowAnr,TwoGesturesWithAnr)10865 TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10866     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10867                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10868                                       .build());
10869 
10870     const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10871     ASSERT_TRUE(sequenceNum);
10872     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10873     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10874 
10875     mWindow->finishEvent(*sequenceNum);
10876     mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10877     ASSERT_TRUE(mDispatcher->waitForIdle());
10878     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10879 
10880     // Now that the window is responsive, let's continue the gesture.
10881     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10882                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10883                                       .build());
10884 
10885     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10886                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10887                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10888                                       .build());
10889 
10890     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10891                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10892                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10893                                       .build());
10894     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10895                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10896                                       .build());
10897     // We already canceled this pointer, so the window shouldn't get any new events.
10898     mWindow->assertNoEvents();
10899 
10900     // Start another one.
10901     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10902                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10903                                       .build());
10904     mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10905 }
10906 
10907 // Send an event to the app and have the app not respond right away. Then remove the app window.
10908 // When the window is removed, the dispatcher will cancel the events for that window.
10909 // So InputDispatcher will enqueue ACTION_CANCEL event as well.
TEST_F(InputDispatcherSingleWindowAnr,AnrAfterWindowRemoval)10910 TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10911     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10912                                                  AINPUT_SOURCE_TOUCHSCREEN,
10913                                                  ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
10914 
10915     const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10916     ASSERT_TRUE(sequenceNum);
10917 
10918     // Remove the window, but the input channel should remain alive.
10919     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10920 
10921     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10922     // Since the window was removed, Dispatcher does not know the PID associated with the window
10923     // anymore, so the policy is notified without the PID.
10924     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10925                                                          /*pid=*/std::nullopt);
10926 
10927     mWindow->finishEvent(*sequenceNum);
10928     // The cancellation was generated when the window was removed, along with the focus event.
10929     mWindow->consumeMotionEvent(
10930             AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
10931     mWindow->consumeFocusEvent(false);
10932     ASSERT_TRUE(mDispatcher->waitForIdle());
10933     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10934 }
10935 
10936 // Send an event to the app and have the app not respond right away. Wait for the policy to be
10937 // notified of the unresponsive window, then remove the app window.
TEST_F(InputDispatcherSingleWindowAnr,AnrFollowedByWindowRemoval)10938 TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10939     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10940                                                  AINPUT_SOURCE_TOUCHSCREEN,
10941                                                  ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
10942 
10943     const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10944     ASSERT_TRUE(sequenceNum);
10945     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10946     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10947 
10948     // Remove the window, but the input channel should remain alive.
10949     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10950 
10951     mWindow->finishEvent(*sequenceNum);
10952     // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10953     mWindow->consumeMotionEvent(
10954             AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
10955     mWindow->consumeFocusEvent(false);
10956     ASSERT_TRUE(mDispatcher->waitForIdle());
10957     // Since the window was removed, Dispatcher does not know the PID associated with the window
10958     // becoming responsive, so the policy is notified without the PID.
10959     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10960 }
10961 
10962 class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
SetUp()10963     virtual void SetUp() override {
10964         InputDispatcherTest::SetUp();
10965 
10966         mApplication = std::make_shared<FakeApplicationHandle>();
10967         mApplication->setDispatchingTimeout(100ms);
10968         mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
10969                                                       ui::LogicalDisplayId::DEFAULT);
10970         mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
10971         // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
10972         mUnfocusedWindow->setWatchOutsideTouch(true);
10973 
10974         mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
10975                                                     ui::LogicalDisplayId::DEFAULT);
10976         mFocusedWindow->setDispatchingTimeout(100ms);
10977         mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
10978 
10979         // Set focused application.
10980         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
10981         mFocusedWindow->setFocusable(true);
10982 
10983         // Expect one focus window exist in display.
10984         mDispatcher->onWindowInfosChanged(
10985                 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
10986         setFocusedWindow(mFocusedWindow);
10987         mFocusedWindow->consumeFocusEvent(true);
10988     }
10989 
TearDown()10990     virtual void TearDown() override {
10991         InputDispatcherTest::TearDown();
10992 
10993         mUnfocusedWindow.clear();
10994         mFocusedWindow.clear();
10995     }
10996 
10997 protected:
10998     std::shared_ptr<FakeApplicationHandle> mApplication;
10999     sp<FakeWindowHandle> mUnfocusedWindow;
11000     sp<FakeWindowHandle> mFocusedWindow;
11001     static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
11002     static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
11003     static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
11004 
tapOnFocusedWindow()11005     void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
11006 
tapOnUnfocusedWindow()11007     void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
11008 
11009 private:
tap(const PointF & location)11010     void tap(const PointF& location) {
11011         ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11012                   injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11013                                    ui::LogicalDisplayId::DEFAULT, location));
11014         ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11015                   injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11016                                  ui::LogicalDisplayId::DEFAULT, location));
11017     }
11018 };
11019 
11020 // If we have 2 windows that are both unresponsive, the one with the shortest timeout
11021 // should be ANR'd first.
TEST_F(InputDispatcherMultiWindowAnr,TwoWindows_BothUnresponsive)11022 TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
11023     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11024               injectMotionEvent(*mDispatcher,
11025                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11026                                                    AINPUT_SOURCE_TOUCHSCREEN)
11027                                         .pointer(PointerBuilder(0, ToolType::FINGER)
11028                                                          .x(FOCUSED_WINDOW_LOCATION.x)
11029                                                          .y(FOCUSED_WINDOW_LOCATION.y))
11030                                         .build()));
11031     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11032               injectMotionEvent(*mDispatcher,
11033                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
11034                                                    AINPUT_SOURCE_TOUCHSCREEN)
11035                                         .pointer(PointerBuilder(0, ToolType::FINGER)
11036                                                          .x(FOCUSED_WINDOW_LOCATION.x)
11037                                                          .y(FOCUSED_WINDOW_LOCATION.y))
11038                                         .build()));
11039     mFocusedWindow->consumeMotionDown();
11040     mFocusedWindow->consumeMotionUp();
11041     mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
11042     // We consumed all events, so no ANR
11043     ASSERT_TRUE(mDispatcher->waitForIdle());
11044     mFakePolicy->assertNotifyAnrWasNotCalled();
11045 
11046     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11047               injectMotionEvent(*mDispatcher,
11048                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11049                                                    AINPUT_SOURCE_TOUCHSCREEN)
11050                                         .pointer(PointerBuilder(0, ToolType::FINGER)
11051                                                          .x(FOCUSED_WINDOW_LOCATION.x)
11052                                                          .y(FOCUSED_WINDOW_LOCATION.y))
11053                                         .build()));
11054     const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
11055     ASSERT_TRUE(unfocusedSequenceNum);
11056 
11057     const std::chrono::duration timeout =
11058             mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
11059     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
11060 
11061     mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
11062     mFocusedWindow->consumeMotionDown();
11063     // This cancel is generated because the connection was unresponsive
11064     mFocusedWindow->consumeMotionCancel();
11065     mFocusedWindow->assertNoEvents();
11066     mUnfocusedWindow->assertNoEvents();
11067     ASSERT_TRUE(mDispatcher->waitForIdle());
11068     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11069                                                        mFocusedWindow->getPid());
11070     mFakePolicy->assertNotifyAnrWasNotCalled();
11071 }
11072 
11073 // If we have 2 windows with identical timeouts that are both unresponsive,
11074 // it doesn't matter which order they should have ANR.
11075 // But we should receive ANR for both.
TEST_F(InputDispatcherMultiWindowAnr,TwoWindows_BothUnresponsiveWithSameTimeout)11076 TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
11077     // Set the timeout for unfocused window to match the focused window
11078     mUnfocusedWindow->setDispatchingTimeout(
11079             mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
11080     mDispatcher->onWindowInfosChanged(
11081             {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
11082 
11083     tapOnFocusedWindow();
11084     // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
11085     // We don't know which window will ANR first. But both of them should happen eventually.
11086     std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
11087                                                               mFocusedWindow->getDispatchingTimeout(
11088                                                                       DISPATCHING_TIMEOUT)),
11089                                                       mFakePolicy->getUnresponsiveWindowToken(0ms)};
11090 
11091     ASSERT_THAT(anrConnectionTokens,
11092                 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
11093                                                 testing::Eq(mUnfocusedWindow->getToken())));
11094 
11095     ASSERT_TRUE(mDispatcher->waitForIdle());
11096     mFakePolicy->assertNotifyAnrWasNotCalled();
11097 
11098     mFocusedWindow->consumeMotionDown();
11099     mFocusedWindow->consumeMotionUp();
11100     mUnfocusedWindow->consumeMotionOutside();
11101 
11102     std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
11103                                                    mFakePolicy->getResponsiveWindowToken()};
11104 
11105     // Both applications should be marked as responsive, in any order
11106     ASSERT_THAT(responsiveTokens,
11107                 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
11108                                                 testing::Eq(mUnfocusedWindow->getToken())));
11109     mFakePolicy->assertNotifyAnrWasNotCalled();
11110 }
11111 
11112 // If a window is already not responding, the second tap on the same window should be ignored.
11113 // We should also log an error to account for the dropped event (not tested here).
11114 // At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
TEST_F(InputDispatcherMultiWindowAnr,DuringAnr_SecondTapIsIgnored)11115 TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
11116     tapOnFocusedWindow();
11117     mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
11118     // Receive the events, but don't respond
11119     const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
11120     ASSERT_TRUE(downEventSequenceNum);
11121     const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
11122     ASSERT_TRUE(upEventSequenceNum);
11123     const std::chrono::duration timeout =
11124             mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
11125     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
11126 
11127     // Tap once again
11128     // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
11129     ASSERT_EQ(InputEventInjectionResult::FAILED,
11130               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11131                                ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
11132     ASSERT_EQ(InputEventInjectionResult::FAILED,
11133               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
11134                              FOCUSED_WINDOW_LOCATION));
11135     // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
11136     // valid touch target
11137     mUnfocusedWindow->assertNoEvents();
11138 
11139     // Consume the first tap
11140     mFocusedWindow->finishEvent(*downEventSequenceNum);
11141     mFocusedWindow->finishEvent(*upEventSequenceNum);
11142     ASSERT_TRUE(mDispatcher->waitForIdle());
11143     // The second tap did not go to the focused window
11144     mFocusedWindow->assertNoEvents();
11145     // Since all events are finished, connection should be deemed healthy again
11146     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11147                                                        mFocusedWindow->getPid());
11148     mFakePolicy->assertNotifyAnrWasNotCalled();
11149 }
11150 
11151 // If you tap outside of all windows, there will not be ANR
TEST_F(InputDispatcherMultiWindowAnr,TapOutsideAllWindows_DoesNotAnr)11152 TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
11153     ASSERT_EQ(InputEventInjectionResult::FAILED,
11154               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11155                                ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
11156     ASSERT_TRUE(mDispatcher->waitForIdle());
11157     mFakePolicy->assertNotifyAnrWasNotCalled();
11158 }
11159 
11160 // Since the focused window is paused, tapping on it should not produce any events
TEST_F(InputDispatcherMultiWindowAnr,Window_CanBePaused)11161 TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
11162     mFocusedWindow->setPaused(true);
11163     mDispatcher->onWindowInfosChanged(
11164             {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
11165 
11166     ASSERT_EQ(InputEventInjectionResult::FAILED,
11167               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11168                                ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
11169 
11170     std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
11171     ASSERT_TRUE(mDispatcher->waitForIdle());
11172     // Should not ANR because the window is paused, and touches shouldn't go to it
11173     mFakePolicy->assertNotifyAnrWasNotCalled();
11174 
11175     mFocusedWindow->assertNoEvents();
11176     mUnfocusedWindow->assertNoEvents();
11177 }
11178 
11179 /**
11180  * If a window is processing a motion event, and then a key event comes in, the key event should
11181  * not get delivered to the focused window until the motion is processed.
11182  * If a different window becomes focused at this time, the key should go to that window instead.
11183  *
11184  * Warning!!!
11185  * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
11186  * and the injection timeout that we specify when injecting the key.
11187  * We must have the injection timeout (100ms) be smaller than
11188  *  KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
11189  *
11190  * If that value changes, this test should also change.
11191  */
TEST_F(InputDispatcherMultiWindowAnr,PendingKey_GoesToNewlyFocusedWindow)11192 TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
11193     // Set a long ANR timeout to prevent it from triggering
11194     mFocusedWindow->setDispatchingTimeout(2s);
11195     mDispatcher->onWindowInfosChanged(
11196             {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
11197 
11198     tapOnUnfocusedWindow();
11199     const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
11200     ASSERT_TRUE(downSequenceNum);
11201     const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
11202     ASSERT_TRUE(upSequenceNum);
11203     // Don't finish the events yet, and send a key
11204     // Injection will succeed because we will eventually give up and send the key to the focused
11205     // window even if motions are still being processed.
11206 
11207     InputEventInjectionResult result =
11208             injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11209                       ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
11210                       /*injectionTimeout=*/100ms);
11211     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11212     // Key will not be sent to the window, yet, because the window is still processing events
11213     // and the key remains pending, waiting for the touch events to be processed.
11214     // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
11215     // under the hood.
11216     static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
11217     mFocusedWindow->assertNoEvents();
11218 
11219     // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
11220     mFocusedWindow->setFocusable(false);
11221     mUnfocusedWindow->setFocusable(true);
11222     mDispatcher->onWindowInfosChanged(
11223             {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
11224     setFocusedWindow(mUnfocusedWindow);
11225 
11226     // Focus events should precede the key events
11227     mUnfocusedWindow->consumeFocusEvent(true);
11228     mFocusedWindow->consumeFocusEvent(false);
11229 
11230     // Finish the tap events, which should unblock dispatcher
11231     mUnfocusedWindow->finishEvent(*downSequenceNum);
11232     mUnfocusedWindow->finishEvent(*upSequenceNum);
11233 
11234     // Now that all queues are cleared and no backlog in the connections, the key event
11235     // can finally go to the newly focused "mUnfocusedWindow".
11236     mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
11237     mFocusedWindow->assertNoEvents();
11238     mUnfocusedWindow->assertNoEvents();
11239     mFakePolicy->assertNotifyAnrWasNotCalled();
11240 }
11241 
11242 // When the touch stream is split across 2 windows, and one of them does not respond,
11243 // then ANR should be raised and the touch should be canceled for the unresponsive window.
11244 // The other window should not be affected by that.
TEST_F(InputDispatcherMultiWindowAnr,SplitTouch_SingleWindowAnr)11245 TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
11246     // Touch Window 1
11247     mDispatcher->notifyMotion(
11248             generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11249                                ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
11250     mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
11251 
11252     // Touch Window 2
11253     mDispatcher->notifyMotion(
11254             generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11255                                ui::LogicalDisplayId::DEFAULT,
11256                                {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
11257 
11258     const std::chrono::duration timeout =
11259             mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
11260     mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
11261 
11262     mUnfocusedWindow->consumeMotionDown();
11263     mFocusedWindow->consumeMotionDown();
11264     // Focused window may or may not receive ACTION_MOVE
11265     // But it should definitely receive ACTION_CANCEL due to the ANR
11266     const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
11267     ASSERT_TRUE(moveOrCancelSequenceNum);
11268     mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
11269     ASSERT_NE(nullptr, event);
11270     ASSERT_EQ(event->getType(), InputEventType::MOTION);
11271     MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
11272     if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
11273         mFocusedWindow->consumeMotionCancel();
11274     } else {
11275         ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
11276     }
11277     ASSERT_TRUE(mDispatcher->waitForIdle());
11278     mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11279                                                        mFocusedWindow->getPid());
11280 
11281     mUnfocusedWindow->assertNoEvents();
11282     mFocusedWindow->assertNoEvents();
11283     mFakePolicy->assertNotifyAnrWasNotCalled();
11284 }
11285 
11286 /**
11287  * If we have no focused window, and a key comes in, we start the ANR timer.
11288  * The focused application should add a focused window before the timer runs out to prevent ANR.
11289  *
11290  * If the user touches another application during this time, the key should be dropped.
11291  * Next, if a new focused window comes in, without toggling the focused application,
11292  * then no ANR should occur.
11293  *
11294  * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
11295  * but in some cases the policy may not update the focused application.
11296  */
TEST_F(InputDispatcherMultiWindowAnr,FocusedWindowWithoutSetFocusedApplication_NoAnr)11297 TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
11298     std::shared_ptr<FakeApplicationHandle> focusedApplication =
11299             std::make_shared<FakeApplicationHandle>();
11300     focusedApplication->setDispatchingTimeout(300ms);
11301     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
11302     // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
11303     mFocusedWindow->setFocusable(false);
11304 
11305     mDispatcher->onWindowInfosChanged(
11306             {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
11307     mFocusedWindow->consumeFocusEvent(false);
11308 
11309     // Send a key. The ANR timer should start because there is no focused window.
11310     // 'focusedApplication' will get blamed if this timer completes.
11311     // Key will not be sent anywhere because we have no focused window. It will remain pending.
11312     InputEventInjectionResult result =
11313             injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11314                       ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
11315                       /*injectionTimeout=*/100ms,
11316                       /*allowKeyRepeat=*/false);
11317     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11318 
11319     // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
11320     // then the injected touches won't cause the focused event to get dropped.
11321     // The dispatcher only checks for whether the queue should be pruned upon queueing.
11322     // If we inject the touch right away and the ANR timer hasn't started, the touch event would
11323     // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
11324     // For this test, it means that the key would get delivered to the window once it becomes
11325     // focused.
11326     std::this_thread::sleep_for(100ms);
11327 
11328     // Touch unfocused window. This should force the pending key to get dropped.
11329     mDispatcher->notifyMotion(
11330             generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11331                                ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
11332 
11333     // We do not consume the motion right away, because that would require dispatcher to first
11334     // process (== drop) the key event, and by that time, ANR will be raised.
11335     // Set the focused window first.
11336     mFocusedWindow->setFocusable(true);
11337     mDispatcher->onWindowInfosChanged(
11338             {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
11339     setFocusedWindow(mFocusedWindow);
11340     mFocusedWindow->consumeFocusEvent(true);
11341     // We do not call "setFocusedApplication" here, even though the newly focused window belongs
11342     // to another application. This could be a bug / behaviour in the policy.
11343 
11344     mUnfocusedWindow->consumeMotionDown();
11345 
11346     ASSERT_TRUE(mDispatcher->waitForIdle());
11347     // Should not ANR because we actually have a focused window. It was just added too slowly.
11348     ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
11349 }
11350 
11351 /**
11352  * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
11353  * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
11354  * dispatcher doesn't prune pointer events incorrectly.
11355  *
11356  * This test reproduces a crash in InputDispatcher.
11357  * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
11358  *
11359  * Keep the currently focused application (mApplication), and have no focused window.
11360  * We set up two additional windows:
11361  * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
11362  * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
11363  * window. This window is not focusable, but is touchable.
11364  *
11365  * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
11366  * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
11367  * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
11368  *
11369  * Now, we touch "Another window". This window is owned by a different application than
11370  * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
11371  * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
11372  * dropping the events from its queue. Ensure that no crash occurs.
11373  *
11374  * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
11375  * This does not affect the test running time.
11376  */
TEST_F(InputDispatcherMultiWindowAnr,PruningInputQueueShouldNotDropPointerEvents)11377 TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
11378     std::shared_ptr<FakeApplicationHandle> systemUiApplication =
11379             std::make_shared<FakeApplicationHandle>();
11380     systemUiApplication->setDispatchingTimeout(3000ms);
11381     mFakePolicy->setStaleEventTimeout(3000ms);
11382     sp<FakeWindowHandle> navigationBar =
11383             sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
11384                                        ui::LogicalDisplayId::DEFAULT);
11385     navigationBar->setFocusable(false);
11386     navigationBar->setWatchOutsideTouch(true);
11387     navigationBar->setFrame(Rect(0, 0, 100, 100));
11388 
11389     mApplication->setDispatchingTimeout(3000ms);
11390     // 'mApplication' is already focused, but we call it again here to make it explicit.
11391     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
11392 
11393     std::shared_ptr<FakeApplicationHandle> anotherApplication =
11394             std::make_shared<FakeApplicationHandle>();
11395     sp<FakeWindowHandle> appWindow =
11396             sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
11397                                        ui::LogicalDisplayId::DEFAULT);
11398     appWindow->setFocusable(false);
11399     appWindow->setFrame(Rect(100, 100, 200, 200));
11400 
11401     mDispatcher->onWindowInfosChanged(
11402             {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
11403     // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
11404     mFocusedWindow->consumeFocusEvent(false);
11405 
11406     // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
11407     // in response.
11408     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11409                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
11410                                       .build());
11411     navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
11412 
11413     // Key will not be sent anywhere because we have no focused window. It will remain pending.
11414     // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
11415     InputEventInjectionResult result =
11416             injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11417                       ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
11418                       /*injectionTimeout=*/100ms,
11419                       /*allowKeyRepeat=*/false);
11420     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11421 
11422     // Finish the gesture - lift up finger and inject ACTION_UP key event
11423     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11424                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
11425                                       .build());
11426     result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
11427                        ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
11428                        /*injectionTimeout=*/100ms,
11429                        /*allowKeyRepeat=*/false);
11430     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11431     // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
11432     // getting any events yet.
11433     navigationBar->assertNoEvents();
11434 
11435     // Now touch "Another window". This touch is going to a different application than the one we
11436     // are waiting for (which is 'mApplication').
11437     // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
11438     // trying to be injected) and to continue processing the rest of the events in the original
11439     // order.
11440     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11441                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
11442                                       .build());
11443     navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
11444     navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
11445     appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
11446 
11447     appWindow->assertNoEvents();
11448     navigationBar->assertNoEvents();
11449 }
11450 
11451 // These tests ensure we cannot send touch events to a window that's positioned behind a window
11452 // that has feature NO_INPUT_CHANNEL.
11453 // Layout:
11454 //   Top (closest to user)
11455 //       mNoInputWindow (above all windows)
11456 //       mBottomWindow
11457 //   Bottom (furthest from user)
11458 class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
SetUp()11459     virtual void SetUp() override {
11460         InputDispatcherTest::SetUp();
11461 
11462         mApplication = std::make_shared<FakeApplicationHandle>();
11463         mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11464                                                     "Window without input channel",
11465                                                     ui::LogicalDisplayId::DEFAULT,
11466                                                     /*createInputChannel=*/false);
11467         mNoInputWindow->setNoInputChannel(true);
11468         mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
11469         // It's perfectly valid for this window to not have an associated input channel
11470 
11471         mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
11472                                                    ui::LogicalDisplayId::DEFAULT);
11473         mBottomWindow->setFrame(Rect(0, 0, 100, 100));
11474 
11475         mDispatcher->onWindowInfosChanged(
11476                 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
11477     }
11478 
11479 protected:
11480     std::shared_ptr<FakeApplicationHandle> mApplication;
11481     sp<FakeWindowHandle> mNoInputWindow;
11482     sp<FakeWindowHandle> mBottomWindow;
11483 };
11484 
TEST_F(InputDispatcherMultiWindowOcclusionTests,NoInputChannelFeature_DropsTouches)11485 TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
11486     PointF touchedPoint = {10, 10};
11487 
11488     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11489                                                  AINPUT_SOURCE_TOUCHSCREEN,
11490                                                  ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
11491 
11492     mNoInputWindow->assertNoEvents();
11493     // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
11494     // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
11495     // and therefore should prevent mBottomWindow from receiving touches
11496     mBottomWindow->assertNoEvents();
11497 }
11498 
11499 /**
11500  * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
11501  * ensure that this window does not receive any touches, and blocks touches to windows underneath.
11502  */
TEST_F(InputDispatcherMultiWindowOcclusionTests,NoInputChannelFeature_DropsTouchesWithValidChannel)11503 TEST_F(InputDispatcherMultiWindowOcclusionTests,
11504        NoInputChannelFeature_DropsTouchesWithValidChannel) {
11505     mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11506                                                 "Window with input channel and NO_INPUT_CHANNEL",
11507                                                 ui::LogicalDisplayId::DEFAULT);
11508 
11509     mNoInputWindow->setNoInputChannel(true);
11510     mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
11511     mDispatcher->onWindowInfosChanged(
11512             {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
11513 
11514     PointF touchedPoint = {10, 10};
11515 
11516     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11517                                                  AINPUT_SOURCE_TOUCHSCREEN,
11518                                                  ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
11519 
11520     mNoInputWindow->assertNoEvents();
11521     mBottomWindow->assertNoEvents();
11522 }
11523 
11524 class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
11525 protected:
11526     std::shared_ptr<FakeApplicationHandle> mApp;
11527     sp<FakeWindowHandle> mWindow;
11528     sp<FakeWindowHandle> mMirror;
11529 
SetUp()11530     virtual void SetUp() override {
11531         InputDispatcherTest::SetUp();
11532         mApp = std::make_shared<FakeApplicationHandle>();
11533         mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11534                                              ui::LogicalDisplayId::DEFAULT);
11535         mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
11536         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
11537         mWindow->setFocusable(true);
11538         mMirror->setFocusable(true);
11539         mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
11540     }
11541 };
11542 
TEST_F(InputDispatcherMirrorWindowFocusTests,CanGetFocus)11543 TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
11544     // Request focus on a mirrored window
11545     setFocusedWindow(mMirror);
11546 
11547     // window gets focused
11548     mWindow->consumeFocusEvent(true);
11549     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
11550             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11551     mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
11552 }
11553 
11554 // A focused & mirrored window remains focused only if the window and its mirror are both
11555 // focusable.
TEST_F(InputDispatcherMirrorWindowFocusTests,FocusedIfAllWindowsFocusable)11556 TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
11557     setFocusedWindow(mMirror);
11558 
11559     // window gets focused because it is above the mirror
11560     mWindow->consumeFocusEvent(true);
11561     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
11562             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11563     mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
11564     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
11565             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11566     mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
11567 
11568     mMirror->setFocusable(false);
11569     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
11570 
11571     // window loses focus since one of the windows associated with the token in not focusable
11572     mWindow->consumeFocusEvent(false);
11573 
11574     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
11575             << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
11576     mWindow->assertNoEvents();
11577 }
11578 
11579 // A focused & mirrored window remains focused until the window and its mirror both become
11580 // invisible.
TEST_F(InputDispatcherMirrorWindowFocusTests,FocusedIfAnyWindowVisible)11581 TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
11582     setFocusedWindow(mMirror);
11583 
11584     // window gets focused
11585     mWindow->consumeFocusEvent(true);
11586     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
11587             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11588     mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
11589     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
11590             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11591     mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
11592 
11593     mMirror->setVisible(false);
11594     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
11595 
11596     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
11597             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11598     mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
11599     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
11600             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11601     mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
11602 
11603     mWindow->setVisible(false);
11604     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
11605 
11606     // window loses focus only after all windows associated with the token become invisible.
11607     mWindow->consumeFocusEvent(false);
11608 
11609     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
11610             << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
11611     mWindow->assertNoEvents();
11612 }
11613 
11614 // A focused & mirrored window remains focused until both windows are removed.
TEST_F(InputDispatcherMirrorWindowFocusTests,FocusedWhileWindowsAlive)11615 TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
11616     setFocusedWindow(mMirror);
11617 
11618     // window gets focused
11619     mWindow->consumeFocusEvent(true);
11620     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
11621             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11622     mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
11623     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
11624             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11625     mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
11626 
11627     // single window is removed but the window token remains focused
11628     mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
11629 
11630     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
11631             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11632     mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
11633     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
11634             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11635     mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
11636 
11637     // Both windows are removed
11638     mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
11639     mWindow->consumeFocusEvent(false);
11640 
11641     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
11642             << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
11643     mWindow->assertNoEvents();
11644 }
11645 
11646 // Focus request can be pending until one window becomes visible.
TEST_F(InputDispatcherMirrorWindowFocusTests,DeferFocusWhenInvisible)11647 TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
11648     // Request focus on an invisible mirror.
11649     mWindow->setVisible(false);
11650     mMirror->setVisible(false);
11651     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
11652     setFocusedWindow(mMirror);
11653 
11654     // Injected key goes to pending queue.
11655     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11656               injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11657                         ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
11658 
11659     mMirror->setVisible(true);
11660     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
11661 
11662     // window gets focused
11663     mWindow->consumeFocusEvent(true);
11664     // window gets the pending key event
11665     mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
11666 }
11667 
11668 class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
11669 protected:
11670     std::shared_ptr<FakeApplicationHandle> mApp;
11671     sp<FakeWindowHandle> mWindow;
11672     sp<FakeWindowHandle> mSecondWindow;
11673 
SetUp()11674     void SetUp() override {
11675         InputDispatcherTest::SetUp();
11676         mApp = std::make_shared<FakeApplicationHandle>();
11677         mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11678                                              ui::LogicalDisplayId::DEFAULT);
11679         mWindow->setFocusable(true);
11680         mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11681                                                    ui::LogicalDisplayId::DEFAULT);
11682         mSecondWindow->setFocusable(true);
11683 
11684         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
11685         mDispatcher->onWindowInfosChanged(
11686                 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11687 
11688         setFocusedWindow(mWindow);
11689         mWindow->consumeFocusEvent(true);
11690     }
11691 
notifyPointerCaptureChanged(const PointerCaptureRequest & request)11692     void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
11693         mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
11694     }
11695 
requestAndVerifyPointerCapture(const sp<FakeWindowHandle> & window,bool enabled)11696     PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
11697                                                          bool enabled) {
11698         mDispatcher->requestPointerCapture(window->getToken(), enabled);
11699         auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
11700         notifyPointerCaptureChanged(request);
11701         window->consumeCaptureEvent(enabled);
11702         return request;
11703     }
11704 };
11705 
TEST_F(InputDispatcherPointerCaptureTests,EnablePointerCaptureWhenFocused)11706 TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
11707     // Ensure that capture cannot be obtained for unfocused windows.
11708     mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11709     mFakePolicy->assertSetPointerCaptureNotCalled();
11710     mSecondWindow->assertNoEvents();
11711 
11712     // Ensure that capture can be enabled from the focus window.
11713     requestAndVerifyPointerCapture(mWindow, true);
11714 
11715     // Ensure that capture cannot be disabled from a window that does not have capture.
11716     mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
11717     mFakePolicy->assertSetPointerCaptureNotCalled();
11718 
11719     // Ensure that capture can be disabled from the window with capture.
11720     requestAndVerifyPointerCapture(mWindow, false);
11721 }
11722 
TEST_F(InputDispatcherPointerCaptureTests,DisablesPointerCaptureAfterWindowLosesFocus)11723 TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
11724     auto request = requestAndVerifyPointerCapture(mWindow, true);
11725 
11726     setFocusedWindow(mSecondWindow);
11727 
11728     // Ensure that the capture disabled event was sent first.
11729     mWindow->consumeCaptureEvent(false);
11730     mWindow->consumeFocusEvent(false);
11731     mSecondWindow->consumeFocusEvent(true);
11732     mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11733 
11734     // Ensure that additional state changes from InputReader are not sent to the window.
11735     notifyPointerCaptureChanged({});
11736     notifyPointerCaptureChanged(request);
11737     notifyPointerCaptureChanged({});
11738     mWindow->assertNoEvents();
11739     mSecondWindow->assertNoEvents();
11740     mFakePolicy->assertSetPointerCaptureNotCalled();
11741 }
11742 
TEST_F(InputDispatcherPointerCaptureTests,UnexpectedStateChangeDisablesPointerCapture)11743 TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
11744     auto request = requestAndVerifyPointerCapture(mWindow, true);
11745 
11746     // InputReader unexpectedly disables and enables pointer capture.
11747     notifyPointerCaptureChanged({});
11748     notifyPointerCaptureChanged(request);
11749 
11750     // Ensure that Pointer Capture is disabled.
11751     mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11752     mWindow->consumeCaptureEvent(false);
11753     mWindow->assertNoEvents();
11754 }
11755 
TEST_F(InputDispatcherPointerCaptureTests,OutOfOrderRequests)11756 TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
11757     requestAndVerifyPointerCapture(mWindow, true);
11758 
11759     // The first window loses focus.
11760     setFocusedWindow(mSecondWindow);
11761     mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11762     mWindow->consumeCaptureEvent(false);
11763 
11764     // Request Pointer Capture from the second window before the notification from InputReader
11765     // arrives.
11766     mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11767     auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
11768 
11769     // InputReader notifies Pointer Capture was disabled (because of the focus change).
11770     notifyPointerCaptureChanged({});
11771 
11772     // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
11773     notifyPointerCaptureChanged(request);
11774 
11775     mSecondWindow->consumeFocusEvent(true);
11776     mSecondWindow->consumeCaptureEvent(true);
11777 }
11778 
TEST_F(InputDispatcherPointerCaptureTests,EnableRequestFollowsSequenceNumbers)11779 TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
11780     // App repeatedly enables and disables capture.
11781     mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11782     auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11783     mDispatcher->requestPointerCapture(mWindow->getToken(), false);
11784     mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11785     mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11786     auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11787 
11788     // InputReader notifies that PointerCapture has been enabled for the first request. Since the
11789     // first request is now stale, this should do nothing.
11790     notifyPointerCaptureChanged(firstRequest);
11791     mWindow->assertNoEvents();
11792 
11793     // InputReader notifies that the second request was enabled.
11794     notifyPointerCaptureChanged(secondRequest);
11795     mWindow->consumeCaptureEvent(true);
11796 }
11797 
TEST_F(InputDispatcherPointerCaptureTests,RapidToggleRequests)11798 TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
11799     requestAndVerifyPointerCapture(mWindow, true);
11800 
11801     // App toggles pointer capture off and on.
11802     mDispatcher->requestPointerCapture(mWindow->getToken(), false);
11803     mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11804 
11805     mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11806     auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11807 
11808     // InputReader notifies that the latest "enable" request was processed, while skipping over the
11809     // preceding "disable" request.
11810     notifyPointerCaptureChanged(enableRequest);
11811 
11812     // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11813     // any notifications.
11814     mWindow->assertNoEvents();
11815 }
11816 
11817 /**
11818  * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11819  * mouse movements don't affect the previous mouse hovering state.
11820  * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11821  * HOVER_MOVE events).
11822  */
TEST_F(InputDispatcherPointerCaptureTests,MouseHoverAndPointerCapture)11823 TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11824     // Mouse hover on the window
11825     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11826                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11827                                       .build());
11828     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11829                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11830                                       .build());
11831 
11832     mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11833     mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11834 
11835     // Start pointer capture
11836     requestAndVerifyPointerCapture(mWindow, true);
11837 
11838     // Send some relative mouse movements and receive them in the window.
11839     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11840                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11841                                       .build());
11842     mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11843                                       WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11844 
11845     // Stop pointer capture
11846     requestAndVerifyPointerCapture(mWindow, false);
11847 
11848     // Continue hovering on the window
11849     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11850                                       .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11851                                       .build());
11852     mWindow->consumeMotionEvent(
11853             AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11854 
11855     mWindow->assertNoEvents();
11856 }
11857 
TEST_F(InputDispatcherPointerCaptureTests,MultiDisplayPointerCapture)11858 TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11859     // The default display is the focused display to begin with.
11860     requestAndVerifyPointerCapture(mWindow, true);
11861 
11862     // Move the second window to a second display, make it the focused window on that display.
11863     mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11864     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11865     setFocusedWindow(mSecondWindow);
11866     mSecondWindow->consumeFocusEvent(true);
11867 
11868     mWindow->assertNoEvents();
11869 
11870     // The second window cannot gain capture because it is not on the focused display.
11871     mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11872     mFakePolicy->assertSetPointerCaptureNotCalled();
11873     mSecondWindow->assertNoEvents();
11874 
11875     // Make the second display the focused display.
11876     mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
11877     mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
11878 
11879     // This causes the first window to lose pointer capture, and it's unable to request capture.
11880     mWindow->consumeCaptureEvent(false);
11881     mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11882 
11883     mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11884     mFakePolicy->assertSetPointerCaptureNotCalled();
11885 
11886     // The second window is now able to gain pointer capture successfully.
11887     requestAndVerifyPointerCapture(mSecondWindow, true);
11888 }
11889 
11890 using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11891 
TEST_F(InputDispatcherPointerCaptureDeathTest,NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher)11892 TEST_F(InputDispatcherPointerCaptureDeathTest,
11893        NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11894     testing::GTEST_FLAG(death_test_style) = "threadsafe";
11895     ScopedSilentDeath _silentDeath;
11896 
11897     mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11898     auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11899 
11900     // Dispatch a pointer changed event with a wrong token.
11901     request.window = mSecondWindow->getToken();
11902     ASSERT_DEATH(
11903             {
11904                 notifyPointerCaptureChanged(request);
11905                 mSecondWindow->consumeCaptureEvent(true);
11906             },
11907             "Unexpected requested window for Pointer Capture.");
11908 }
11909 
11910 class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11911 protected:
11912     constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
11913 
11914     constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11915     static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11916 
11917     constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11918     static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11919 
11920     // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11921     constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11922     static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11923     static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11924                   MAXIMUM_OBSCURING_OPACITY);
11925 
11926     static constexpr gui::Uid TOUCHED_APP_UID{10001};
11927     static constexpr gui::Uid APP_B_UID{10002};
11928     static constexpr gui::Uid APP_C_UID{10003};
11929 
11930     sp<FakeWindowHandle> mTouchWindow;
11931 
SetUp()11932     virtual void SetUp() override {
11933         InputDispatcherTest::SetUp();
11934         mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
11935         mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11936     }
11937 
TearDown()11938     virtual void TearDown() override {
11939         InputDispatcherTest::TearDown();
11940         mTouchWindow.clear();
11941     }
11942 
getOccludingWindow(gui::Uid uid,std::string name,TouchOcclusionMode mode,float alpha=1.0f)11943     sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
11944                                             float alpha = 1.0f) {
11945         sp<FakeWindowHandle> window = getWindow(uid, name);
11946         window->setTouchable(false);
11947         window->setTouchOcclusionMode(mode);
11948         window->setAlpha(alpha);
11949         return window;
11950     }
11951 
getWindow(gui::Uid uid,std::string name)11952     sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
11953         std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11954         sp<FakeWindowHandle> window =
11955                 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
11956         // Generate an arbitrary PID based on the UID
11957         window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
11958         return window;
11959     }
11960 
touch(const std::vector<PointF> & points={PointF{100, 200}})11961     void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
11962         mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11963                                                      AINPUT_SOURCE_TOUCHSCREEN,
11964                                                      ui::LogicalDisplayId::DEFAULT, points));
11965     }
11966 };
11967 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithBlockUntrustedOcclusionMode_BlocksTouch)11968 TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
11969     const sp<FakeWindowHandle>& w =
11970             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
11971     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
11972 
11973     touch();
11974 
11975     mTouchWindow->assertNoEvents();
11976 }
11977 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch)11978 TEST_F(InputDispatcherUntrustedTouchesTest,
11979        WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11980     const sp<FakeWindowHandle>& w =
11981             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
11982     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
11983 
11984     touch();
11985 
11986     mTouchWindow->assertNoEvents();
11987 }
11988 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch)11989 TEST_F(InputDispatcherUntrustedTouchesTest,
11990        WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11991     const sp<FakeWindowHandle>& w =
11992             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
11993     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
11994 
11995     touch();
11996 
11997     w->assertNoEvents();
11998 }
11999 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithAllowOcclusionMode_AllowsTouch)12000 TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
12001     const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
12002     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12003 
12004     touch();
12005 
12006     mTouchWindow->consumeAnyMotionDown();
12007 }
12008 
TEST_F(InputDispatcherUntrustedTouchesTest,TouchOutsideOccludingWindow_AllowsTouch)12009 TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
12010     const sp<FakeWindowHandle>& w =
12011             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
12012     w->setFrame(Rect(0, 0, 50, 50));
12013     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12014 
12015     touch({PointF{100, 100}});
12016 
12017     mTouchWindow->consumeAnyMotionDown();
12018 }
12019 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowFromSameUid_AllowsTouch)12020 TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
12021     const sp<FakeWindowHandle>& w =
12022             getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
12023     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12024 
12025     touch();
12026 
12027     mTouchWindow->consumeAnyMotionDown();
12028 }
12029 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithZeroOpacity_AllowsTouch)12030 TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
12031     const sp<FakeWindowHandle>& w =
12032             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
12033     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12034 
12035     touch();
12036 
12037     mTouchWindow->consumeAnyMotionDown();
12038 }
12039 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithZeroOpacity_DoesNotReceiveTouch)12040 TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
12041     const sp<FakeWindowHandle>& w =
12042             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
12043     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12044 
12045     touch();
12046 
12047     w->assertNoEvents();
12048 }
12049 
12050 /**
12051  * This is important to make sure apps can't indirectly learn the position of touches (outside vs
12052  * inside) while letting them pass-through. Note that even though touch passes through the occluding
12053  * window, the occluding window will still receive ACTION_OUTSIDE event.
12054  */
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent)12055 TEST_F(InputDispatcherUntrustedTouchesTest,
12056        WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
12057     const sp<FakeWindowHandle>& w =
12058             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
12059     w->setWatchOutsideTouch(true);
12060     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12061 
12062     touch();
12063 
12064     w->consumeMotionOutside();
12065 }
12066 
TEST_F(InputDispatcherUntrustedTouchesTest,OutsideEvent_HasZeroCoordinates)12067 TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
12068     const sp<FakeWindowHandle>& w =
12069             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
12070     w->setWatchOutsideTouch(true);
12071     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12072 
12073     touch();
12074 
12075     w->consumeMotionOutsideWithZeroedCoords();
12076 }
12077 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithOpacityBelowThreshold_AllowsTouch)12078 TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
12079     const sp<FakeWindowHandle>& w =
12080             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12081                                OPACITY_BELOW_THRESHOLD);
12082     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12083 
12084     touch();
12085 
12086     mTouchWindow->consumeAnyMotionDown();
12087 }
12088 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithOpacityAtThreshold_AllowsTouch)12089 TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
12090     const sp<FakeWindowHandle>& w =
12091             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12092                                MAXIMUM_OBSCURING_OPACITY);
12093     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12094 
12095     touch();
12096 
12097     mTouchWindow->consumeAnyMotionDown();
12098 }
12099 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithOpacityAboveThreshold_BlocksTouch)12100 TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
12101     const sp<FakeWindowHandle>& w =
12102             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12103                                OPACITY_ABOVE_THRESHOLD);
12104     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12105 
12106     touch();
12107 
12108     mTouchWindow->assertNoEvents();
12109 }
12110 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowsWithCombinedOpacityAboveThreshold_BlocksTouch)12111 TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
12112     // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
12113     const sp<FakeWindowHandle>& w1 =
12114             getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
12115                                OPACITY_BELOW_THRESHOLD);
12116     const sp<FakeWindowHandle>& w2 =
12117             getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
12118                                OPACITY_BELOW_THRESHOLD);
12119     mDispatcher->onWindowInfosChanged(
12120             {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12121 
12122     touch();
12123 
12124     mTouchWindow->assertNoEvents();
12125 }
12126 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowsWithCombinedOpacityBelowThreshold_AllowsTouch)12127 TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
12128     // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
12129     const sp<FakeWindowHandle>& w1 =
12130             getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
12131                                OPACITY_FAR_BELOW_THRESHOLD);
12132     const sp<FakeWindowHandle>& w2 =
12133             getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
12134                                OPACITY_FAR_BELOW_THRESHOLD);
12135     mDispatcher->onWindowInfosChanged(
12136             {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12137 
12138     touch();
12139 
12140     mTouchWindow->consumeAnyMotionDown();
12141 }
12142 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch)12143 TEST_F(InputDispatcherUntrustedTouchesTest,
12144        WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
12145     const sp<FakeWindowHandle>& wB =
12146             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12147                                OPACITY_BELOW_THRESHOLD);
12148     const sp<FakeWindowHandle>& wC =
12149             getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12150                                OPACITY_BELOW_THRESHOLD);
12151     mDispatcher->onWindowInfosChanged(
12152             {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12153 
12154     touch();
12155 
12156     mTouchWindow->consumeAnyMotionDown();
12157 }
12158 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch)12159 TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
12160     const sp<FakeWindowHandle>& wB =
12161             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12162                                OPACITY_BELOW_THRESHOLD);
12163     const sp<FakeWindowHandle>& wC =
12164             getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12165                                OPACITY_ABOVE_THRESHOLD);
12166     mDispatcher->onWindowInfosChanged(
12167             {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12168 
12169     touch();
12170 
12171     mTouchWindow->assertNoEvents();
12172 }
12173 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch)12174 TEST_F(InputDispatcherUntrustedTouchesTest,
12175        WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
12176     const sp<FakeWindowHandle>& wA =
12177             getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12178                                OPACITY_BELOW_THRESHOLD);
12179     const sp<FakeWindowHandle>& wB =
12180             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12181                                OPACITY_ABOVE_THRESHOLD);
12182     mDispatcher->onWindowInfosChanged(
12183             {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12184 
12185     touch();
12186 
12187     mTouchWindow->assertNoEvents();
12188 }
12189 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch)12190 TEST_F(InputDispatcherUntrustedTouchesTest,
12191        WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
12192     const sp<FakeWindowHandle>& wA =
12193             getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12194                                OPACITY_ABOVE_THRESHOLD);
12195     const sp<FakeWindowHandle>& wB =
12196             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12197                                OPACITY_BELOW_THRESHOLD);
12198     mDispatcher->onWindowInfosChanged(
12199             {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12200 
12201     touch();
12202 
12203     mTouchWindow->consumeAnyMotionDown();
12204 }
12205 
TEST_F(InputDispatcherUntrustedTouchesTest,SelfWindowWithOpacityAboveThreshold_AllowsTouch)12206 TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
12207     const sp<FakeWindowHandle>& w =
12208             getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12209                                OPACITY_ABOVE_THRESHOLD);
12210     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12211 
12212     touch();
12213 
12214     mTouchWindow->consumeAnyMotionDown();
12215 }
12216 
TEST_F(InputDispatcherUntrustedTouchesTest,SelfWindowWithBlockUntrustedMode_AllowsTouch)12217 TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
12218     const sp<FakeWindowHandle>& w =
12219             getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
12220     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12221 
12222     touch();
12223 
12224     mTouchWindow->consumeAnyMotionDown();
12225 }
12226 
TEST_F(InputDispatcherUntrustedTouchesTest,OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch)12227 TEST_F(InputDispatcherUntrustedTouchesTest,
12228        OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
12229     mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
12230     const sp<FakeWindowHandle>& w =
12231             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
12232     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12233 
12234     touch();
12235 
12236     mTouchWindow->assertNoEvents();
12237 }
12238 
TEST_F(InputDispatcherUntrustedTouchesTest,OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch)12239 TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
12240     mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
12241     const sp<FakeWindowHandle>& w =
12242             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
12243     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12244 
12245     touch();
12246 
12247     mTouchWindow->consumeAnyMotionDown();
12248 }
12249 
TEST_F(InputDispatcherUntrustedTouchesTest,OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch)12250 TEST_F(InputDispatcherUntrustedTouchesTest,
12251        OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
12252     mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
12253     const sp<FakeWindowHandle>& w =
12254             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12255                                OPACITY_ABOVE_THRESHOLD);
12256     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12257 
12258     touch();
12259 
12260     mTouchWindow->consumeAnyMotionDown();
12261 }
12262 
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch)12263 TEST_F(InputDispatcherUntrustedTouchesTest,
12264        WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
12265     const sp<FakeWindowHandle>& w1 =
12266             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
12267                                OPACITY_BELOW_THRESHOLD);
12268     const sp<FakeWindowHandle>& w2 =
12269             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12270                                OPACITY_BELOW_THRESHOLD);
12271     mDispatcher->onWindowInfosChanged(
12272             {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12273 
12274     touch();
12275 
12276     mTouchWindow->assertNoEvents();
12277 }
12278 
12279 /**
12280  * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
12281  * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
12282  * (which alone would result in allowing touches) does not affect the blocking behavior.
12283  */
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch)12284 TEST_F(InputDispatcherUntrustedTouchesTest,
12285        WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
12286     const sp<FakeWindowHandle>& wB =
12287             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
12288                                OPACITY_BELOW_THRESHOLD);
12289     const sp<FakeWindowHandle>& wC =
12290             getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12291                                OPACITY_BELOW_THRESHOLD);
12292     mDispatcher->onWindowInfosChanged(
12293             {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12294 
12295     touch();
12296 
12297     mTouchWindow->assertNoEvents();
12298 }
12299 
12300 /**
12301  * This test is testing that a window from a different UID but with same application token doesn't
12302  * block the touch. Apps can share the application token for close UI collaboration for example.
12303  */
TEST_F(InputDispatcherUntrustedTouchesTest,WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch)12304 TEST_F(InputDispatcherUntrustedTouchesTest,
12305        WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
12306     const sp<FakeWindowHandle>& w =
12307             getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
12308     w->setApplicationToken(mTouchWindow->getApplicationToken());
12309     mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
12310 
12311     touch();
12312 
12313     mTouchWindow->consumeAnyMotionDown();
12314 }
12315 
12316 class InputDispatcherDragTests : public InputDispatcherTest {
12317 protected:
12318     std::shared_ptr<FakeApplicationHandle> mApp;
12319     sp<FakeWindowHandle> mWindow;
12320     sp<FakeWindowHandle> mSecondWindow;
12321     sp<FakeWindowHandle> mDragWindow;
12322     sp<FakeWindowHandle> mSpyWindow;
12323     // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
12324     static constexpr int32_t MOUSE_POINTER_ID = 1;
12325 
SetUp()12326     void SetUp() override {
12327         InputDispatcherTest::SetUp();
12328         mApp = std::make_shared<FakeApplicationHandle>();
12329         mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12330                                              ui::LogicalDisplayId::DEFAULT);
12331         mWindow->setFrame(Rect(0, 0, 100, 100));
12332 
12333         mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12334                                                    ui::LogicalDisplayId::DEFAULT);
12335         mSecondWindow->setFrame(Rect(100, 0, 200, 100));
12336 
12337         mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
12338                                                 ui::LogicalDisplayId::DEFAULT);
12339         mSpyWindow->setSpy(true);
12340         mSpyWindow->setTrustedOverlay(true);
12341         mSpyWindow->setFrame(Rect(0, 0, 200, 100));
12342 
12343         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
12344         mDispatcher->onWindowInfosChanged(
12345                 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
12346                  {},
12347                  0,
12348                  0});
12349     }
12350 
injectDown(int fromSource=AINPUT_SOURCE_TOUCHSCREEN)12351     void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
12352         switch (fromSource) {
12353             case AINPUT_SOURCE_TOUCHSCREEN:
12354                 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12355                           injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12356                                            ui::LogicalDisplayId::DEFAULT, {50, 50}))
12357                         << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12358                 break;
12359             case AINPUT_SOURCE_STYLUS:
12360                 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12361                           injectMotionEvent(*mDispatcher,
12362                                             MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12363                                                                AINPUT_SOURCE_STYLUS)
12364                                                     .buttonState(
12365                                                             AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
12366                                                     .pointer(PointerBuilder(0, ToolType::STYLUS)
12367                                                                      .x(50)
12368                                                                      .y(50))
12369                                                     .build()));
12370                 break;
12371             case AINPUT_SOURCE_MOUSE:
12372                 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12373                           injectMotionEvent(*mDispatcher,
12374                                             MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12375                                                                AINPUT_SOURCE_MOUSE)
12376                                                     .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
12377                                                     .pointer(PointerBuilder(MOUSE_POINTER_ID,
12378                                                                             ToolType::MOUSE)
12379                                                                      .x(50)
12380                                                                      .y(50))
12381                                                     .build()));
12382                 break;
12383             default:
12384                 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
12385         }
12386 
12387         // Window should receive motion event.
12388         mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12389         // Spy window should also receive motion event
12390         mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12391     }
12392 
12393     // Start performing drag, we will create a drag window and transfer touch to it.
12394     // @param sendDown : if true, send a motion down on first window before perform drag and drop.
12395     // Returns true on success.
startDrag(bool sendDown=true,int fromSource=AINPUT_SOURCE_TOUCHSCREEN)12396     bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
12397         if (sendDown) {
12398             injectDown(fromSource);
12399         }
12400 
12401         // The drag window covers the entire display
12402         mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
12403                                                  ui::LogicalDisplayId::DEFAULT);
12404         mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
12405         mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
12406                                             *mWindow->getInfo(), *mSecondWindow->getInfo()},
12407                                            {},
12408                                            0,
12409                                            0});
12410 
12411         // Transfer touch focus to the drag window
12412         bool transferred =
12413                 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
12414                                                   /*isDragDrop=*/true);
12415         if (transferred) {
12416             mWindow->consumeMotionCancel();
12417             mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12418                                            AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12419         }
12420         return transferred;
12421     }
12422 };
12423 
TEST_F(InputDispatcherDragTests,DragEnterAndDragExit)12424 TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
12425     startDrag();
12426 
12427     // Move on window.
12428     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12429               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
12430                                 ui::LogicalDisplayId::DEFAULT, {50, 50}))
12431             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12432     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12433                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12434     mWindow->consumeDragEvent(false, 50, 50);
12435     mSecondWindow->assertNoEvents();
12436 
12437     // Move to another window.
12438     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12439               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
12440                                 ui::LogicalDisplayId::DEFAULT, {150, 50}))
12441             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12442     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12443                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12444     mWindow->consumeDragEvent(true, 150, 50);
12445     mSecondWindow->consumeDragEvent(false, 50, 50);
12446 
12447     // Move back to original window.
12448     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12449               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
12450                                 ui::LogicalDisplayId::DEFAULT, {50, 50}))
12451             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12452     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12453                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12454     mWindow->consumeDragEvent(false, 50, 50);
12455     mSecondWindow->consumeDragEvent(true, -50, 50);
12456 
12457     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12458               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
12459                              {50, 50}))
12460             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12461     mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12462     mWindow->assertNoEvents();
12463     mSecondWindow->assertNoEvents();
12464 }
12465 
TEST_F(InputDispatcherDragTests,DragEnterAndPointerDownPilfersPointers)12466 TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
12467     startDrag();
12468 
12469     // No cancel event after drag start
12470     mSpyWindow->assertNoEvents();
12471 
12472     const MotionEvent secondFingerDownEvent =
12473             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12474                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12475                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12476                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12477                     .build();
12478     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12479               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12480                                 InputEventInjectionSync::WAIT_FOR_RESULT))
12481             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12482 
12483     // Receives cancel for first pointer after next pointer down
12484     mSpyWindow->consumeMotionCancel();
12485     mSpyWindow->consumeMotionDown();
12486 
12487     mSpyWindow->assertNoEvents();
12488 }
12489 
TEST_F(InputDispatcherDragTests,DragAndDrop)12490 TEST_F(InputDispatcherDragTests, DragAndDrop) {
12491     startDrag();
12492 
12493     // Move on window.
12494     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12495               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
12496                                 ui::LogicalDisplayId::DEFAULT, {50, 50}))
12497             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12498     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12499                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12500     mWindow->consumeDragEvent(false, 50, 50);
12501     mSecondWindow->assertNoEvents();
12502 
12503     // Move to another window.
12504     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12505               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
12506                                 ui::LogicalDisplayId::DEFAULT, {150, 50}))
12507             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12508     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12509                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12510     mWindow->consumeDragEvent(true, 150, 50);
12511     mSecondWindow->consumeDragEvent(false, 50, 50);
12512 
12513     // drop to another window.
12514     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12515               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
12516                              {150, 50}))
12517             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12518     mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12519     mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
12520     mWindow->assertNoEvents();
12521     mSecondWindow->assertNoEvents();
12522 }
12523 
TEST_F(InputDispatcherDragTests,DragAndDropNotCancelledIfSomeOtherPointerIsPilfered)12524 TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
12525     startDrag();
12526 
12527     // No cancel event after drag start
12528     mSpyWindow->assertNoEvents();
12529 
12530     const MotionEvent secondFingerDownEvent =
12531             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12532                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12533                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12534                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12535                     .build();
12536     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12537               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12538                                 InputEventInjectionSync::WAIT_FOR_RESULT))
12539             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12540 
12541     // Receives cancel for first pointer after next pointer down
12542     mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
12543     mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
12544     mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
12545 
12546     mSpyWindow->assertNoEvents();
12547 
12548     // Spy window calls pilfer pointers
12549     EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
12550     mDragWindow->assertNoEvents();
12551 
12552     const MotionEvent firstFingerMoveEvent =
12553             MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12554                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12555                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
12556                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12557                     .build();
12558     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12559               injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
12560                                 InputEventInjectionSync::WAIT_FOR_RESULT))
12561             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12562 
12563     // Drag window should still receive the new event
12564     mDragWindow->consumeMotionEvent(
12565             AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
12566     mDragWindow->assertNoEvents();
12567 }
12568 
TEST_F(InputDispatcherDragTests,StylusDragAndDrop)12569 TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
12570     startDrag(true, AINPUT_SOURCE_STYLUS);
12571 
12572     // Move on window and keep button pressed.
12573     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12574               injectMotionEvent(*mDispatcher,
12575                                 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12576                                         .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
12577                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
12578                                         .build()))
12579             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12580     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12581                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12582     mWindow->consumeDragEvent(false, 50, 50);
12583     mSecondWindow->assertNoEvents();
12584 
12585     // Move to another window and release button, expect to drop item.
12586     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12587               injectMotionEvent(*mDispatcher,
12588                                 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12589                                         .buttonState(0)
12590                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
12591                                         .build()))
12592             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12593     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12594                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12595     mWindow->assertNoEvents();
12596     mSecondWindow->assertNoEvents();
12597     mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
12598 
12599     // nothing to the window.
12600     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12601               injectMotionEvent(*mDispatcher,
12602                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
12603                                         .buttonState(0)
12604                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
12605                                         .build()))
12606             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12607     mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12608     mWindow->assertNoEvents();
12609     mSecondWindow->assertNoEvents();
12610 }
12611 
TEST_F(InputDispatcherDragTests,DragAndDropOnInvalidWindow)12612 TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
12613     startDrag();
12614 
12615     // Set second window invisible.
12616     mSecondWindow->setVisible(false);
12617     mDispatcher->onWindowInfosChanged(
12618             {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12619 
12620     // Move on window.
12621     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12622               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
12623                                 ui::LogicalDisplayId::DEFAULT, {50, 50}))
12624             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12625     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12626                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12627     mWindow->consumeDragEvent(false, 50, 50);
12628     mSecondWindow->assertNoEvents();
12629 
12630     // Move to another window.
12631     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12632               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
12633                                 ui::LogicalDisplayId::DEFAULT, {150, 50}))
12634             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12635     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12636                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12637     mWindow->consumeDragEvent(true, 150, 50);
12638     mSecondWindow->assertNoEvents();
12639 
12640     // drop to another window.
12641     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12642               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
12643                              {150, 50}))
12644             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12645     mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12646     mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12647     mWindow->assertNoEvents();
12648     mSecondWindow->assertNoEvents();
12649 }
12650 
TEST_F(InputDispatcherDragTests,NoDragAndDropWhenMultiFingers)12651 TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
12652     // Ensure window could track pointerIds if it didn't support split touch.
12653     mWindow->setPreventSplitting(true);
12654 
12655     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12656               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12657                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
12658             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12659     mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12660 
12661     const MotionEvent secondFingerDownEvent =
12662             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12663                     .displayId(ui::LogicalDisplayId::DEFAULT)
12664                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12665                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12666                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
12667                     .build();
12668     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12669               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12670                                 InputEventInjectionSync::WAIT_FOR_RESULT))
12671             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12672     mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
12673 
12674     // Should not perform drag and drop when window has multi fingers.
12675     ASSERT_FALSE(startDrag(false));
12676 }
12677 
TEST_F(InputDispatcherDragTests,DragAndDropWhenSplitTouch)12678 TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
12679     // First down on second window.
12680     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12681               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12682                                ui::LogicalDisplayId::DEFAULT, {150, 50}))
12683             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12684 
12685     mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12686 
12687     // Second down on first window.
12688     const MotionEvent secondFingerDownEvent =
12689             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12690                     .displayId(ui::LogicalDisplayId::DEFAULT)
12691                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12692                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12693                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12694                     .build();
12695     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12696               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12697                                 InputEventInjectionSync::WAIT_FOR_RESULT))
12698             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12699     mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12700     mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
12701 
12702     // Perform drag and drop from first window.
12703     ASSERT_TRUE(startDrag(false));
12704 
12705     // Move on window.
12706     const MotionEvent secondFingerMoveEvent =
12707             MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12708                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12709                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12710                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12711                     .build();
12712     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12713               injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
12714                                 InputEventInjectionSync::WAIT_FOR_RESULT));
12715     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12716                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12717     mWindow->consumeDragEvent(false, 50, 50);
12718     mSecondWindow->consumeMotionMove();
12719 
12720     // Release the drag pointer should perform drop.
12721     const MotionEvent secondFingerUpEvent =
12722             MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12723                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12724                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12725                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12726                     .build();
12727     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12728               injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
12729                                 InputEventInjectionSync::WAIT_FOR_RESULT));
12730     mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12731     mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
12732     mWindow->assertNoEvents();
12733     mSecondWindow->consumeMotionMove();
12734 }
12735 
TEST_F(InputDispatcherDragTests,DragAndDropWhenMultiDisplays)12736 TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
12737     startDrag();
12738 
12739     // Update window of second display.
12740     sp<FakeWindowHandle> windowInSecondary =
12741             sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
12742     mDispatcher->onWindowInfosChanged(
12743             {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12744               *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12745              {},
12746              0,
12747              0});
12748 
12749     // Let second display has a touch state.
12750     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12751               injectMotionEvent(*mDispatcher,
12752                                 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12753                                                    AINPUT_SOURCE_TOUCHSCREEN)
12754                                         .displayId(SECOND_DISPLAY_ID)
12755                                         .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
12756                                         .build()));
12757     windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
12758     // Update window again.
12759     mDispatcher->onWindowInfosChanged(
12760             {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12761               *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12762              {},
12763              0,
12764              0});
12765 
12766     // Move on window.
12767     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12768               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
12769                                 ui::LogicalDisplayId::DEFAULT, {50, 50}))
12770             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12771     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12772                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12773     mWindow->consumeDragEvent(false, 50, 50);
12774     mSecondWindow->assertNoEvents();
12775 
12776     // Move to another window.
12777     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12778               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
12779                                 ui::LogicalDisplayId::DEFAULT, {150, 50}))
12780             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12781     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12782                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12783     mWindow->consumeDragEvent(true, 150, 50);
12784     mSecondWindow->consumeDragEvent(false, 50, 50);
12785 
12786     // drop to another window.
12787     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12788               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
12789                              {150, 50}))
12790             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12791     mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12792     mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
12793     mWindow->assertNoEvents();
12794     mSecondWindow->assertNoEvents();
12795 }
12796 
TEST_F(InputDispatcherDragTests,MouseDragAndDrop)12797 TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
12798     startDrag(true, AINPUT_SOURCE_MOUSE);
12799     // Move on window.
12800     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12801               injectMotionEvent(*mDispatcher,
12802                                 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12803                                         .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
12804                                         .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
12805                                                          .x(50)
12806                                                          .y(50))
12807                                         .build()))
12808             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12809     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12810                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12811     mWindow->consumeDragEvent(false, 50, 50);
12812     mSecondWindow->assertNoEvents();
12813 
12814     // Move to another window.
12815     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12816               injectMotionEvent(*mDispatcher,
12817                                 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12818                                         .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
12819                                         .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
12820                                                          .x(150)
12821                                                          .y(50))
12822                                         .build()))
12823             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12824     mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12825                                    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12826     mWindow->consumeDragEvent(true, 150, 50);
12827     mSecondWindow->consumeDragEvent(false, 50, 50);
12828 
12829     // drop to another window.
12830     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12831               injectMotionEvent(*mDispatcher,
12832                                 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12833                                         .buttonState(0)
12834                                         .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
12835                                                          .x(150)
12836                                                          .y(50))
12837                                         .build()))
12838             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12839     mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
12840     mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
12841     mWindow->assertNoEvents();
12842     mSecondWindow->assertNoEvents();
12843 }
12844 
12845 /**
12846  * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12847  * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12848  */
TEST_F(InputDispatcherDragTests,DragAndDropFinishedWhenCancelCurrentTouch)12849 TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12850     // Down on second window
12851     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12852               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12853                                ui::LogicalDisplayId::DEFAULT, {150, 50}))
12854             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12855 
12856     ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12857     ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12858 
12859     // Down on first window
12860     const MotionEvent secondFingerDownEvent =
12861             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12862                     .displayId(ui::LogicalDisplayId::DEFAULT)
12863                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12864                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12865                     .build();
12866     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12867               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12868                                 InputEventInjectionSync::WAIT_FOR_RESULT))
12869             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12870     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12871     ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12872     ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12873 
12874     // Start drag on first window
12875     ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12876 
12877     // Trigger cancel
12878     mDispatcher->cancelCurrentTouch();
12879     ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
12880     ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
12881                                                              AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
12882     ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12883 
12884     ASSERT_TRUE(mDispatcher->waitForIdle());
12885     // The D&D finished with nullptr
12886     mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12887 
12888     // Remove drag window
12889     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12890 
12891     // Complete the first event stream, even though the injection will fail because there aren't any
12892     // valid targets to dispatch this event to. This is still needed to make the input stream
12893     // consistent
12894     ASSERT_EQ(InputEventInjectionResult::FAILED,
12895               injectMotionEvent(*mDispatcher,
12896                                 MotionEventBuilder(ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
12897                                         .displayId(ui::LogicalDisplayId::DEFAULT)
12898                                         .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
12899                                                          .x(150)
12900                                                          .y(50))
12901                                         .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
12902                                                          .x(50)
12903                                                          .y(50))
12904                                         .build(),
12905                                 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT));
12906 
12907     // Inject a simple gesture, ensure dispatcher not crashed
12908     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12909               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12910                                ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
12911             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12912     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12913 
12914     const MotionEvent moveEvent =
12915             MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12916                     .displayId(ui::LogicalDisplayId::DEFAULT)
12917                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12918                     .build();
12919     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12920               injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12921                                 InputEventInjectionSync::WAIT_FOR_RESULT))
12922             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12923     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12924 
12925     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12926               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
12927                              {50, 50}))
12928             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12929     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12930 }
12931 
TEST_F(InputDispatcherDragTests,NoDragAndDropWithHoveringPointer)12932 TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12933     // Start hovering over the window.
12934     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12935               injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
12936                                 ui::LogicalDisplayId::DEFAULT, {50, 50}));
12937 
12938     ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12939     ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12940 
12941     ASSERT_FALSE(startDrag(/*sendDown=*/false))
12942             << "Drag and drop should not work with a hovering pointer";
12943 }
12944 
12945 /**
12946  * Two devices, we use the second pointer of Device A to start the drag, during the drag process, if
12947  * we perform a click using Device B, the dispatcher should work well.
12948  */
TEST_F(InputDispatcherDragTests,DragAndDropWhenSplitTouchAndMultiDevice)12949 TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouchAndMultiDevice) {
12950     const DeviceId deviceA = 1;
12951     const DeviceId deviceB = 2;
12952     // First down on second window with deviceA.
12953     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12954                                       .deviceId(deviceA)
12955                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12956                                       .build());
12957     mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12958                                             WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12959 
12960     // Second down on first window with deviceA
12961     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12962                                       .deviceId(deviceA)
12963                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12964                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(50).y(50))
12965                                       .build());
12966     mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12967                                       WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12968     mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12969                                             WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12970 
12971     // Perform drag and drop from first window.
12972     ASSERT_TRUE(startDrag(/*sendDown=*/false));
12973 
12974     // Click first window with device B, we should ensure dispatcher work well.
12975     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
12976                                       .deviceId(deviceB)
12977                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12978                                       .build());
12979     mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
12980                                       WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12981 
12982     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
12983                                       .deviceId(deviceB)
12984                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12985                                       .build());
12986     mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB),
12987                                       WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12988 
12989     // Move with device A.
12990     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12991                                       .deviceId(deviceA)
12992                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12993                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
12994                                       .build());
12995 
12996     mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12997                                           WithDisplayId(ui::LogicalDisplayId::DEFAULT),
12998                                           WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
12999     mWindow->consumeDragEvent(false, 51, 51);
13000     mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
13001                                             WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
13002 
13003     // Releasing the drag pointer should cause drop.
13004     mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
13005                                       .deviceId(deviceA)
13006                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
13007                                       .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
13008                                       .build());
13009     mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
13010                                           WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13011                                           WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
13012     mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
13013     mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
13014                                             WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
13015 
13016     // Release all pointers.
13017     mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13018                                       .deviceId(deviceA)
13019                                       .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
13020                                       .build());
13021     mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
13022                                             WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
13023     mWindow->assertNoEvents();
13024 }
13025 
13026 class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
13027 
TEST_F(InputDispatcherDropInputFeatureTest,WindowDropsInput)13028 TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
13029     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13030     sp<FakeWindowHandle> window =
13031             sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
13032                                        ui::LogicalDisplayId::DEFAULT);
13033     window->setDropInput(true);
13034     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
13035     window->setFocusable(true);
13036     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
13037     setFocusedWindow(window);
13038     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
13039 
13040     // With the flag set, window should not get any input
13041     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
13042     window->assertNoEvents();
13043 
13044     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
13045                                                  AINPUT_SOURCE_TOUCHSCREEN,
13046                                                  ui::LogicalDisplayId::DEFAULT));
13047     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
13048                                                  ui::LogicalDisplayId::DEFAULT));
13049     mDispatcher->waitForIdle();
13050     window->assertNoEvents();
13051 
13052     // With the flag cleared, the window should get input
13053     window->setDropInput(false);
13054     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
13055 
13056     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
13057     window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
13058 
13059     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
13060                                                  AINPUT_SOURCE_TOUCHSCREEN,
13061                                                  ui::LogicalDisplayId::DEFAULT));
13062     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13063     window->assertNoEvents();
13064 }
13065 
TEST_F(InputDispatcherDropInputFeatureTest,ObscuredWindowDropsInput)13066 TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
13067     std::shared_ptr<FakeApplicationHandle> obscuringApplication =
13068             std::make_shared<FakeApplicationHandle>();
13069     sp<FakeWindowHandle> obscuringWindow =
13070             sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
13071                                        ui::LogicalDisplayId::DEFAULT);
13072     obscuringWindow->setFrame(Rect(0, 0, 50, 50));
13073     obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
13074     obscuringWindow->setTouchable(false);
13075     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13076     sp<FakeWindowHandle> window =
13077             sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
13078                                        ui::LogicalDisplayId::DEFAULT);
13079     window->setDropInputIfObscured(true);
13080     window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
13081     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
13082     window->setFocusable(true);
13083     mDispatcher->onWindowInfosChanged(
13084             {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
13085     setFocusedWindow(window);
13086     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
13087 
13088     // With the flag set, window should not get any input
13089     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
13090     window->assertNoEvents();
13091 
13092     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
13093                                                  AINPUT_SOURCE_TOUCHSCREEN,
13094                                                  ui::LogicalDisplayId::DEFAULT));
13095     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
13096                                                  ui::LogicalDisplayId::DEFAULT));
13097     window->assertNoEvents();
13098 
13099     // With the flag cleared, the window should get input
13100     window->setDropInputIfObscured(false);
13101     mDispatcher->onWindowInfosChanged(
13102             {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
13103 
13104     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
13105     window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
13106 
13107     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
13108                                                  AINPUT_SOURCE_TOUCHSCREEN,
13109                                                  ui::LogicalDisplayId::DEFAULT));
13110     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
13111                               AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
13112     window->assertNoEvents();
13113 }
13114 
TEST_F(InputDispatcherDropInputFeatureTest,UnobscuredWindowGetsInput)13115 TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
13116     std::shared_ptr<FakeApplicationHandle> obscuringApplication =
13117             std::make_shared<FakeApplicationHandle>();
13118     sp<FakeWindowHandle> obscuringWindow =
13119             sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
13120                                        ui::LogicalDisplayId::DEFAULT);
13121     obscuringWindow->setFrame(Rect(0, 0, 50, 50));
13122     obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
13123     obscuringWindow->setTouchable(false);
13124     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13125     sp<FakeWindowHandle> window =
13126             sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
13127                                        ui::LogicalDisplayId::DEFAULT);
13128     window->setDropInputIfObscured(true);
13129     window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
13130     mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
13131     window->setFocusable(true);
13132     mDispatcher->onWindowInfosChanged(
13133             {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
13134     setFocusedWindow(window);
13135     window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
13136 
13137     // With the flag set, window should not get any input
13138     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
13139     window->assertNoEvents();
13140 
13141     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
13142                                                  AINPUT_SOURCE_TOUCHSCREEN,
13143                                                  ui::LogicalDisplayId::DEFAULT));
13144     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
13145                                                  ui::LogicalDisplayId::DEFAULT));
13146     window->assertNoEvents();
13147 
13148     // When the window is no longer obscured because it went on top, it should get input
13149     mDispatcher->onWindowInfosChanged(
13150             {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
13151 
13152     mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
13153     window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
13154 
13155     mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
13156                                                  AINPUT_SOURCE_TOUCHSCREEN,
13157                                                  ui::LogicalDisplayId::DEFAULT));
13158     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13159     window->assertNoEvents();
13160 }
13161 
13162 class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
13163 protected:
13164     std::shared_ptr<FakeApplicationHandle> mApp;
13165     std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
13166     sp<FakeWindowHandle> mWindow;
13167     sp<FakeWindowHandle> mSecondWindow;
13168     sp<FakeWindowHandle> mThirdWindow;
13169 
SetUp()13170     void SetUp() override {
13171         InputDispatcherTest::SetUp();
13172 
13173         mApp = std::make_shared<FakeApplicationHandle>();
13174         mSecondaryApp = std::make_shared<FakeApplicationHandle>();
13175         mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
13176                                              ui::LogicalDisplayId::DEFAULT);
13177         mWindow->setFocusable(true);
13178         setFocusedWindow(mWindow);
13179         mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
13180                                                    ui::LogicalDisplayId::DEFAULT);
13181         mSecondWindow->setFocusable(true);
13182         mThirdWindow =
13183                 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
13184                                            "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
13185         mThirdWindow->setFocusable(true);
13186 
13187         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
13188         mDispatcher->onWindowInfosChanged(
13189                 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
13190                  {},
13191                  0,
13192                  0});
13193         mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
13194         mWindow->consumeFocusEvent(true);
13195 
13196         // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
13197         if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
13198                                         WINDOW_UID, /*hasPermission=*/true,
13199                                         ui::LogicalDisplayId::DEFAULT)) {
13200             mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
13201             mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
13202             mThirdWindow->assertNoEvents();
13203         }
13204 
13205         // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
13206         if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
13207                                         SECONDARY_WINDOW_UID, /*hasPermission=*/true,
13208                                         SECOND_DISPLAY_ID)) {
13209             mWindow->assertNoEvents();
13210             mSecondWindow->assertNoEvents();
13211             mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
13212         }
13213     }
13214 
changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode,gui::Pid pid,gui::Uid uid,bool hasPermission)13215     void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
13216                                                    bool hasPermission) {
13217         ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
13218                                                 ui::LogicalDisplayId::DEFAULT));
13219         mWindow->consumeTouchModeEvent(inTouchMode);
13220         mSecondWindow->consumeTouchModeEvent(inTouchMode);
13221         mThirdWindow->assertNoEvents();
13222     }
13223 };
13224 
TEST_F(InputDispatcherTouchModeChangedTests,FocusedWindowCanChangeTouchMode)13225 TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
13226     const WindowInfo& windowInfo = *mWindow->getInfo();
13227     changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
13228                                               windowInfo.ownerPid, windowInfo.ownerUid,
13229                                               /* hasPermission=*/false);
13230 }
13231 
TEST_F(InputDispatcherTouchModeChangedTests,NonFocusedWindowOwnerCannotChangeTouchMode)13232 TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
13233     const WindowInfo& windowInfo = *mWindow->getInfo();
13234     gui::Pid ownerPid = windowInfo.ownerPid;
13235     gui::Uid ownerUid = windowInfo.ownerUid;
13236     mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
13237     ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
13238                                              ownerUid, /*hasPermission=*/false,
13239                                              ui::LogicalDisplayId::DEFAULT));
13240     mWindow->assertNoEvents();
13241     mSecondWindow->assertNoEvents();
13242 }
13243 
TEST_F(InputDispatcherTouchModeChangedTests,NonWindowOwnerMayChangeTouchModeOnPermissionGranted)13244 TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
13245     const WindowInfo& windowInfo = *mWindow->getInfo();
13246     gui::Pid ownerPid = windowInfo.ownerPid;
13247     gui::Uid ownerUid = windowInfo.ownerUid;
13248     mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
13249     changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
13250                                               ownerUid, /*hasPermission=*/true);
13251 }
13252 
TEST_F(InputDispatcherTouchModeChangedTests,EventIsNotGeneratedIfNotChangingTouchMode)13253 TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
13254     const WindowInfo& windowInfo = *mWindow->getInfo();
13255     ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
13256                                              windowInfo.ownerPid, windowInfo.ownerUid,
13257                                              /*hasPermission=*/true,
13258                                              ui::LogicalDisplayId::DEFAULT));
13259     mWindow->assertNoEvents();
13260     mSecondWindow->assertNoEvents();
13261 }
13262 
TEST_F(InputDispatcherTouchModeChangedTests,ChangeTouchOnSecondaryDisplayOnly)13263 TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
13264     const WindowInfo& windowInfo = *mThirdWindow->getInfo();
13265     ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
13266                                             windowInfo.ownerPid, windowInfo.ownerUid,
13267                                             /*hasPermission=*/true, SECOND_DISPLAY_ID));
13268     mWindow->assertNoEvents();
13269     mSecondWindow->assertNoEvents();
13270     mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
13271 }
13272 
TEST_F(InputDispatcherTouchModeChangedTests,CanChangeTouchModeWhenOwningLastInteractedWindow)13273 TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
13274     // Interact with the window first.
13275     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13276               injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
13277             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
13278     mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
13279 
13280     // Then remove focus.
13281     mWindow->setFocusable(false);
13282     mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
13283 
13284     // Assert that caller can switch touch mode by owning one of the last interacted window.
13285     const WindowInfo& windowInfo = *mWindow->getInfo();
13286     ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
13287                                             windowInfo.ownerPid, windowInfo.ownerUid,
13288                                             /*hasPermission=*/false,
13289                                             ui::LogicalDisplayId::DEFAULT));
13290 }
13291 
13292 class InputDispatcherSpyWindowTest : public InputDispatcherTest {
13293 public:
createSpy()13294     sp<FakeWindowHandle> createSpy() {
13295         std::shared_ptr<FakeApplicationHandle> application =
13296                 std::make_shared<FakeApplicationHandle>();
13297         std::string name = "Fake Spy ";
13298         name += std::to_string(mSpyCount++);
13299         sp<FakeWindowHandle> spy =
13300                 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
13301                                            ui::LogicalDisplayId::DEFAULT);
13302         spy->setSpy(true);
13303         spy->setTrustedOverlay(true);
13304         return spy;
13305     }
13306 
createForeground()13307     sp<FakeWindowHandle> createForeground() {
13308         std::shared_ptr<FakeApplicationHandle> application =
13309                 std::make_shared<FakeApplicationHandle>();
13310         sp<FakeWindowHandle> window =
13311                 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
13312                                            ui::LogicalDisplayId::DEFAULT);
13313         window->setFocusable(true);
13314         return window;
13315     }
13316 
13317 private:
13318     int mSpyCount{0};
13319 };
13320 
13321 using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
13322 /**
13323  * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
13324  */
TEST_F(InputDispatcherSpyWindowDeathTest,UntrustedSpy_AbortsDispatcher)13325 TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
13326     testing::GTEST_FLAG(death_test_style) = "threadsafe";
13327     ScopedSilentDeath _silentDeath;
13328 
13329     auto spy = createSpy();
13330     spy->setTrustedOverlay(false);
13331     ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
13332                  ".* not a trusted overlay");
13333 }
13334 
13335 /**
13336  * Input injection into a display with a spy window but no foreground windows should succeed.
13337  */
TEST_F(InputDispatcherSpyWindowTest,NoForegroundWindow)13338 TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
13339     auto spy = createSpy();
13340     mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
13341 
13342     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13343               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13344                                ui::LogicalDisplayId::DEFAULT))
13345             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13346     spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13347 }
13348 
13349 /**
13350  * Verify the order in which different input windows receive events. The touched foreground window
13351  * (if there is one) should always receive the event first. When there are multiple spy windows, the
13352  * spy windows will receive the event according to their Z-order, where the top-most spy window will
13353  * receive events before ones belows it.
13354  *
13355  * Here, we set up a scenario with four windows in the following Z order from the top:
13356  *    spy1, spy2, window, spy3.
13357  * We then inject an event and verify that the foreground "window" receives it first, followed by
13358  * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
13359  * window.
13360  */
TEST_F(InputDispatcherSpyWindowTest,ReceivesInputInOrder)13361 TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
13362     auto window = createForeground();
13363     auto spy1 = createSpy();
13364     auto spy2 = createSpy();
13365     auto spy3 = createSpy();
13366     mDispatcher->onWindowInfosChanged(
13367             {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
13368     const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
13369     const size_t numChannels = channels.size();
13370 
13371     base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
13372     if (!epollFd.ok()) {
13373         FAIL() << "Failed to create epoll fd";
13374     }
13375 
13376     for (size_t i = 0; i < numChannels; i++) {
13377         struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
13378         if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
13379             FAIL() << "Failed to add fd to epoll";
13380         }
13381     }
13382 
13383     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13384               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13385                                ui::LogicalDisplayId::DEFAULT))
13386             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13387 
13388     std::vector<size_t> eventOrder;
13389     std::vector<struct epoll_event> events(numChannels);
13390     for (;;) {
13391         const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
13392                                     (100ms).count());
13393         if (nFds < 0) {
13394             FAIL() << "Failed to call epoll_wait";
13395         }
13396         if (nFds == 0) {
13397             break; // epoll_wait timed out
13398         }
13399         for (int i = 0; i < nFds; i++) {
13400             ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
13401             eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
13402             channels[i]->consumeMotionDown();
13403         }
13404     }
13405 
13406     // Verify the order in which the events were received.
13407     EXPECT_EQ(3u, eventOrder.size());
13408     EXPECT_EQ(2u, eventOrder[0]); // index 2: window
13409     EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
13410     EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
13411 }
13412 
13413 /**
13414  * A spy window using the NOT_TOUCHABLE flag does not receive events.
13415  */
TEST_F(InputDispatcherSpyWindowTest,NotTouchable)13416 TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
13417     auto window = createForeground();
13418     auto spy = createSpy();
13419     spy->setTouchable(false);
13420     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13421 
13422     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13423               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13424                                ui::LogicalDisplayId::DEFAULT))
13425             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13426     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13427     spy->assertNoEvents();
13428 }
13429 
13430 /**
13431  * A spy window will only receive gestures that originate within its touchable region. Gestures that
13432  * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
13433  * to the window.
13434  */
TEST_F(InputDispatcherSpyWindowTest,TouchableRegion)13435 TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
13436     auto window = createForeground();
13437     auto spy = createSpy();
13438     spy->setTouchableRegion(Region{{0, 0, 20, 20}});
13439     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13440 
13441     // Inject an event outside the spy window's touchable region.
13442     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13443               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13444                                ui::LogicalDisplayId::DEFAULT))
13445             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13446     window->consumeMotionDown();
13447     spy->assertNoEvents();
13448     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13449               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13450                              ui::LogicalDisplayId::DEFAULT))
13451             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13452     window->consumeMotionUp();
13453     spy->assertNoEvents();
13454 
13455     // Inject an event inside the spy window's touchable region.
13456     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13457               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13458                                ui::LogicalDisplayId::DEFAULT, {5, 10}))
13459             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13460     window->consumeMotionDown();
13461     spy->consumeMotionDown();
13462 }
13463 
13464 /**
13465  * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
13466  * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
13467  */
TEST_F(InputDispatcherSpyWindowTest,WatchOutsideTouches)13468 TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
13469     auto window = createForeground();
13470     window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
13471     auto spy = createSpy();
13472     spy->setWatchOutsideTouch(true);
13473     spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
13474     spy->setFrame(Rect{0, 0, 20, 20});
13475     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13476 
13477     // Inject an event outside the spy window's frame and touchable region.
13478     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13479               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13480                                ui::LogicalDisplayId::DEFAULT, {100, 200}))
13481             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13482     window->consumeMotionDown();
13483     spy->consumeMotionOutsideWithZeroedCoords();
13484 }
13485 
13486 /**
13487  * Even when a spy window spans over multiple foreground windows, the spy should receive all
13488  * pointers that are down within its bounds.
13489  */
TEST_F(InputDispatcherSpyWindowTest,ReceivesMultiplePointers)13490 TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
13491     auto windowLeft = createForeground();
13492     windowLeft->setFrame({0, 0, 100, 200});
13493     auto windowRight = createForeground();
13494     windowRight->setFrame({100, 0, 200, 200});
13495     auto spy = createSpy();
13496     spy->setFrame({0, 0, 200, 200});
13497     mDispatcher->onWindowInfosChanged(
13498             {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
13499 
13500     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13501               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13502                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
13503             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13504     windowLeft->consumeMotionDown();
13505     spy->consumeMotionDown();
13506 
13507     const MotionEvent secondFingerDownEvent =
13508             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13509                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
13510                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13511                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13512                     .build();
13513     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13514               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
13515                                 InputEventInjectionSync::WAIT_FOR_RESULT))
13516             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13517     windowRight->consumeMotionDown();
13518     spy->consumeMotionPointerDown(/*pointerIndex=*/1);
13519 }
13520 
13521 /**
13522  * When the first pointer lands outside the spy window and the second pointer lands inside it, the
13523  * the spy should receive the second pointer with ACTION_DOWN.
13524  */
TEST_F(InputDispatcherSpyWindowTest,ReceivesSecondPointerAsDown)13525 TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
13526     auto window = createForeground();
13527     window->setFrame({0, 0, 200, 200});
13528     auto spyRight = createSpy();
13529     spyRight->setFrame({100, 0, 200, 200});
13530     mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
13531 
13532     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13533               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13534                                ui::LogicalDisplayId::DEFAULT, {50, 50}))
13535             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13536     window->consumeMotionDown();
13537     spyRight->assertNoEvents();
13538 
13539     const MotionEvent secondFingerDownEvent =
13540             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13541                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
13542                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13543                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13544                     .build();
13545     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13546               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
13547                                 InputEventInjectionSync::WAIT_FOR_RESULT))
13548             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13549     window->consumeMotionPointerDown(/*pointerIndex=*/1);
13550     spyRight->consumeMotionDown();
13551 }
13552 
13553 /**
13554  * The spy window should not be able to affect whether or not touches are split. Only the foreground
13555  * windows should be allowed to control split touch.
13556  */
TEST_F(InputDispatcherSpyWindowTest,SplitIfNoForegroundWindowTouched)13557 TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
13558     // This spy window prevents touch splitting. However, we still expect to split touches
13559     // because a foreground window has not disabled splitting.
13560     auto spy = createSpy();
13561     spy->setPreventSplitting(true);
13562 
13563     auto window = createForeground();
13564     window->setFrame(Rect(0, 0, 100, 100));
13565 
13566     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13567 
13568     // First finger down, no window touched.
13569     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13570               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13571                                ui::LogicalDisplayId::DEFAULT, {100, 200}))
13572             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13573     spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13574     window->assertNoEvents();
13575 
13576     // Second finger down on window, the window should receive touch down.
13577     const MotionEvent secondFingerDownEvent =
13578             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13579                     .displayId(ui::LogicalDisplayId::DEFAULT)
13580                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
13581                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13582                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13583                     .build();
13584     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13585               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
13586                                 InputEventInjectionSync::WAIT_FOR_RESULT))
13587             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13588 
13589     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13590     spy->consumeMotionPointerDown(/*pointerIndex=*/1);
13591 }
13592 
13593 /**
13594  * A spy window will usually be implemented as an un-focusable window. Verify that these windows
13595  * do not receive key events.
13596  */
TEST_F(InputDispatcherSpyWindowTest,UnfocusableSpyDoesNotReceiveKeyEvents)13597 TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
13598     auto spy = createSpy();
13599     spy->setFocusable(false);
13600 
13601     auto window = createForeground();
13602     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13603     setFocusedWindow(window);
13604     window->consumeFocusEvent(true);
13605 
13606     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
13607             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
13608     window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
13609 
13610     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
13611             << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
13612     window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
13613 
13614     spy->assertNoEvents();
13615 }
13616 
13617 using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
13618 
13619 /**
13620  * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
13621  * are currently sent to any other windows - including other spy windows - will also be cancelled.
13622  */
TEST_F(InputDispatcherPilferPointersTest,PilferPointers)13623 TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
13624     auto window = createForeground();
13625     auto spy1 = createSpy();
13626     auto spy2 = createSpy();
13627     mDispatcher->onWindowInfosChanged(
13628             {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
13629 
13630     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13631               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13632                                ui::LogicalDisplayId::DEFAULT))
13633             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13634     window->consumeMotionDown();
13635     spy1->consumeMotionDown();
13636     spy2->consumeMotionDown();
13637 
13638     // Pilfer pointers from the second spy window.
13639     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
13640     spy2->assertNoEvents();
13641     spy1->consumeMotionCancel();
13642     window->consumeMotionCancel();
13643 
13644     // The rest of the gesture should only be sent to the second spy window.
13645     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13646               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
13647                                 ui::LogicalDisplayId::DEFAULT))
13648             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13649     spy2->consumeMotionMove();
13650     spy1->assertNoEvents();
13651     window->assertNoEvents();
13652 }
13653 
13654 /**
13655  * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
13656  * in the middle of the gesture.
13657  */
TEST_F(InputDispatcherPilferPointersTest,CanPilferAfterWindowIsRemovedMidStream)13658 TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
13659     auto window = createForeground();
13660     auto spy = createSpy();
13661     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13662 
13663     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13664               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13665                                ui::LogicalDisplayId::DEFAULT))
13666             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13667     window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13668     spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13669 
13670     window->releaseChannel();
13671 
13672     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13673 
13674     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13675               injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13676                              ui::LogicalDisplayId::DEFAULT))
13677             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13678     spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
13679 }
13680 
13681 /**
13682  * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
13683  * the spy, but not to any other windows.
13684  */
TEST_F(InputDispatcherPilferPointersTest,ContinuesToReceiveGestureAfterPilfer)13685 TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
13686     auto spy = createSpy();
13687     auto window = createForeground();
13688 
13689     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13690 
13691     // First finger down on the window and the spy.
13692     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13693               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13694                                ui::LogicalDisplayId::DEFAULT, {100, 200}))
13695             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13696     spy->consumeMotionDown();
13697     window->consumeMotionDown();
13698 
13699     // Spy window pilfers the pointers.
13700     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13701     window->consumeMotionCancel();
13702 
13703     // Second finger down on the window and spy, but the window should not receive the pointer down.
13704     const MotionEvent secondFingerDownEvent =
13705             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13706                     .displayId(ui::LogicalDisplayId::DEFAULT)
13707                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
13708                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13709                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13710                     .build();
13711     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13712               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
13713                                 InputEventInjectionSync::WAIT_FOR_RESULT))
13714             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13715 
13716     spy->consumeMotionPointerDown(/*pointerIndex=*/1);
13717 
13718     // Third finger goes down outside all windows, so injection should fail.
13719     const MotionEvent thirdFingerDownEvent =
13720             MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13721                     .displayId(ui::LogicalDisplayId::DEFAULT)
13722                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
13723                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13724                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13725                     .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
13726                     .build();
13727     ASSERT_EQ(InputEventInjectionResult::FAILED,
13728               injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
13729                                 InputEventInjectionSync::WAIT_FOR_RESULT))
13730             << "Inject motion event should return InputEventInjectionResult::FAILED";
13731 
13732     spy->assertNoEvents();
13733     window->assertNoEvents();
13734 }
13735 
13736 /**
13737  * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
13738  */
TEST_F(InputDispatcherPilferPointersTest,PartiallyPilferRequiredPointers)13739 TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
13740     auto spy = createSpy();
13741     spy->setFrame(Rect(0, 0, 100, 100));
13742     auto window = createForeground();
13743     window->setFrame(Rect(0, 0, 200, 200));
13744 
13745     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13746 
13747     // First finger down on the window only
13748     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13749               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13750                                ui::LogicalDisplayId::DEFAULT, {150, 150}))
13751             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13752     window->consumeMotionDown();
13753 
13754     // Second finger down on the spy and window
13755     const MotionEvent secondFingerDownEvent =
13756             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13757                     .displayId(ui::LogicalDisplayId::DEFAULT)
13758                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
13759                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13760                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
13761                     .build();
13762     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13763               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
13764                                 InputEventInjectionSync::WAIT_FOR_RESULT))
13765             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13766     spy->consumeMotionDown();
13767     window->consumeMotionPointerDown(1);
13768 
13769     // Third finger down on the spy and window
13770     const MotionEvent thirdFingerDownEvent =
13771             MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13772                     .displayId(ui::LogicalDisplayId::DEFAULT)
13773                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
13774                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13775                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
13776                     .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
13777                     .build();
13778     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13779               injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
13780                                 InputEventInjectionSync::WAIT_FOR_RESULT))
13781             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13782     spy->consumeMotionPointerDown(1);
13783     window->consumeMotionPointerDown(2);
13784 
13785     // Spy window pilfers the pointers.
13786     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13787     window->consumeMotionPointerUp(/*pointerIdx=*/2,
13788                                    AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13789                                          WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13790                                          WithPointerCount(3)));
13791     window->consumeMotionPointerUp(/*pointerIdx=*/1,
13792                                    AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13793                                          WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13794                                          WithPointerCount(2)));
13795 
13796     spy->assertNoEvents();
13797     window->assertNoEvents();
13798 }
13799 
13800 /**
13801  * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
13802  * other windows should be canceled. If this results in the cancellation of all pointers for some
13803  * window, then that window should receive ACTION_CANCEL.
13804  */
TEST_F(InputDispatcherPilferPointersTest,PilferAllRequiredPointers)13805 TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
13806     auto spy = createSpy();
13807     spy->setFrame(Rect(0, 0, 100, 100));
13808     auto window = createForeground();
13809     window->setFrame(Rect(0, 0, 200, 200));
13810 
13811     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13812 
13813     // First finger down on both spy and window
13814     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13815               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13816                                ui::LogicalDisplayId::DEFAULT, {10, 10}))
13817             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13818     window->consumeMotionDown();
13819     spy->consumeMotionDown();
13820 
13821     // Second finger down on the spy and window
13822     const MotionEvent secondFingerDownEvent =
13823             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13824                     .displayId(ui::LogicalDisplayId::DEFAULT)
13825                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
13826                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13827                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13828                     .build();
13829     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13830               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
13831                                 InputEventInjectionSync::WAIT_FOR_RESULT))
13832             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13833     spy->consumeMotionPointerDown(1);
13834     window->consumeMotionPointerDown(1);
13835 
13836     // Spy window pilfers the pointers.
13837     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13838     window->consumeMotionCancel();
13839 
13840     spy->assertNoEvents();
13841     window->assertNoEvents();
13842 }
13843 
13844 /**
13845  * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
13846  * be sent to other windows
13847  */
TEST_F(InputDispatcherPilferPointersTest,CanReceivePointersAfterPilfer)13848 TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
13849     auto spy = createSpy();
13850     spy->setFrame(Rect(0, 0, 100, 100));
13851     auto window = createForeground();
13852     window->setFrame(Rect(0, 0, 200, 200));
13853 
13854     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13855 
13856     // First finger down on both window and spy
13857     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13858               injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13859                                ui::LogicalDisplayId::DEFAULT, {10, 10}))
13860             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13861     window->consumeMotionDown();
13862     spy->consumeMotionDown();
13863 
13864     // Spy window pilfers the pointers.
13865     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13866     window->consumeMotionCancel();
13867 
13868     // Second finger down on the window only
13869     const MotionEvent secondFingerDownEvent =
13870             MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13871                     .displayId(ui::LogicalDisplayId::DEFAULT)
13872                     .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
13873                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13874                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
13875                     .build();
13876     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
13877               injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
13878                                 InputEventInjectionSync::WAIT_FOR_RESULT))
13879             << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13880     window->consumeMotionDown();
13881     window->assertNoEvents();
13882 
13883     // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
13884     spy->consumeMotionMove();
13885     spy->assertNoEvents();
13886 }
13887 
13888 /**
13889  * A window on the left and a window on the right. Also, a spy window that's above all of the
13890  * windows, and spanning both left and right windows.
13891  * Send simultaneous motion streams from two different devices, one to the left window, and another
13892  * to the right window.
13893  * Pilfer from spy window.
13894  * Check that the pilfering only affects the pointers that are actually being received by the spy.
13895  */
TEST_F(InputDispatcherPilferPointersTest,MultiDevicePilfer_legacy)13896 TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
13897     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
13898     sp<FakeWindowHandle> spy = createSpy();
13899     spy->setFrame(Rect(0, 0, 200, 200));
13900     sp<FakeWindowHandle> leftWindow = createForeground();
13901     leftWindow->setFrame(Rect(0, 0, 100, 100));
13902 
13903     sp<FakeWindowHandle> rightWindow = createForeground();
13904     rightWindow->setFrame(Rect(100, 0, 200, 100));
13905 
13906     constexpr int32_t stylusDeviceId = 1;
13907     constexpr int32_t touchDeviceId = 2;
13908 
13909     mDispatcher->onWindowInfosChanged(
13910             {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13911 
13912     // Stylus down on left window and spy
13913     mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13914                                       .deviceId(stylusDeviceId)
13915                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13916                                       .build());
13917     leftWindow->consumeMotionEvent(
13918             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13919     spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13920 
13921     // Finger down on right window and spy - but spy already has stylus
13922     mDispatcher->notifyMotion(
13923             MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13924                     .deviceId(touchDeviceId)
13925                     .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13926                     .build());
13927     rightWindow->consumeMotionEvent(
13928             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13929     spy->assertNoEvents();
13930 
13931     // Act: pilfer from spy. Spy is currently receiving touch events.
13932     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13933     leftWindow->consumeMotionEvent(
13934             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13935     rightWindow->consumeMotionEvent(
13936             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13937 
13938     // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13939     mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13940                                       .deviceId(stylusDeviceId)
13941                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13942                                       .build());
13943     mDispatcher->notifyMotion(
13944             MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13945                     .deviceId(touchDeviceId)
13946                     .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13947                     .build());
13948     spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
13949 
13950     spy->assertNoEvents();
13951     leftWindow->assertNoEvents();
13952     rightWindow->assertNoEvents();
13953 }
13954 
13955 /**
13956  * A window on the left and a window on the right. Also, a spy window that's above all of the
13957  * windows, and spanning both left and right windows.
13958  * Send simultaneous motion streams from two different devices, one to the left window, and another
13959  * to the right window.
13960  * Pilfer from spy window.
13961  * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13962  * The spy should receive both the touch and the stylus events after pilfer.
13963  */
TEST_F(InputDispatcherPilferPointersTest,MultiDevicePilfer)13964 TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13965     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13966     sp<FakeWindowHandle> spy = createSpy();
13967     spy->setFrame(Rect(0, 0, 200, 200));
13968     sp<FakeWindowHandle> leftWindow = createForeground();
13969     leftWindow->setFrame(Rect(0, 0, 100, 100));
13970 
13971     sp<FakeWindowHandle> rightWindow = createForeground();
13972     rightWindow->setFrame(Rect(100, 0, 200, 100));
13973 
13974     constexpr int32_t stylusDeviceId = 1;
13975     constexpr int32_t touchDeviceId = 2;
13976 
13977     mDispatcher->onWindowInfosChanged(
13978             {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13979 
13980     // Stylus down on left window and spy
13981     mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13982                                       .deviceId(stylusDeviceId)
13983                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13984                                       .build());
13985     leftWindow->consumeMotionEvent(
13986             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13987     spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13988 
13989     // Finger down on right window and spy
13990     mDispatcher->notifyMotion(
13991             MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13992                     .deviceId(touchDeviceId)
13993                     .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13994                     .build());
13995     rightWindow->consumeMotionEvent(
13996             AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13997     spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13998 
13999     // Act: pilfer from spy. Spy is currently receiving touch events.
14000     EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
14001     leftWindow->consumeMotionEvent(
14002             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
14003     rightWindow->consumeMotionEvent(
14004             AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
14005 
14006     // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
14007     // Instead of sending the two MOVE events for each input device together, and then receiving
14008     // them both, process them one at at time. InputConsumer is always in the batching mode, which
14009     // means that the two MOVE events will be initially put into a batch. Once the events are
14010     // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
14011     // on the implementation of InputConsumer), which would mean that the order of the received
14012     // events could be different depending on whether there are 1 or 2 events pending in the
14013     // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
14014     // avoid this confusing behaviour, send and receive each MOVE event separately.
14015     mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
14016                                       .deviceId(stylusDeviceId)
14017                                       .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
14018                                       .build());
14019     spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
14020     mDispatcher->notifyMotion(
14021             MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
14022                     .deviceId(touchDeviceId)
14023                     .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
14024                     .build());
14025     spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
14026 
14027     spy->assertNoEvents();
14028     leftWindow->assertNoEvents();
14029     rightWindow->assertNoEvents();
14030 }
14031 
TEST_F(InputDispatcherPilferPointersTest,NoPilferingWithHoveringPointers)14032 TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
14033     auto window = createForeground();
14034     auto spy = createSpy();
14035     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
14036 
14037     mDispatcher->notifyMotion(
14038             MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
14039                     .deviceId(1)
14040                     .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
14041                     .build());
14042     window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14043     spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14044 
14045     // Pilfer pointers from the spy window should fail.
14046     EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
14047     spy->assertNoEvents();
14048     window->assertNoEvents();
14049 }
14050 
14051 class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
14052 public:
setupStylusOverlayScenario()14053     std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
14054         std::shared_ptr<FakeApplicationHandle> overlayApplication =
14055                 std::make_shared<FakeApplicationHandle>();
14056         sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
14057                                                                   "Stylus interceptor window",
14058                                                                   ui::LogicalDisplayId::DEFAULT);
14059         overlay->setFocusable(false);
14060         overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
14061         overlay->setTouchable(false);
14062         overlay->setInterceptsStylus(true);
14063         overlay->setTrustedOverlay(true);
14064 
14065         std::shared_ptr<FakeApplicationHandle> application =
14066                 std::make_shared<FakeApplicationHandle>();
14067         sp<FakeWindowHandle> window =
14068                 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
14069                                            ui::LogicalDisplayId::DEFAULT);
14070         window->setFocusable(true);
14071         window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
14072 
14073         mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
14074         mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
14075         setFocusedWindow(window);
14076         window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
14077         return {std::move(overlay), std::move(window)};
14078     }
14079 
sendFingerEvent(int32_t action)14080     void sendFingerEvent(int32_t action) {
14081         mDispatcher->notifyMotion(
14082                 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
14083                                    ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
14084     }
14085 
sendStylusEvent(int32_t action)14086     void sendStylusEvent(int32_t action) {
14087         NotifyMotionArgs motionArgs =
14088                 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
14089                                    ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
14090         motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
14091         mDispatcher->notifyMotion(motionArgs);
14092     }
14093 };
14094 
14095 using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
14096 
TEST_F(InputDispatcherStylusInterceptorDeathTest,UntrustedOverlay_AbortsDispatcher)14097 TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
14098     testing::GTEST_FLAG(death_test_style) = "threadsafe";
14099     ScopedSilentDeath _silentDeath;
14100 
14101     auto [overlay, window] = setupStylusOverlayScenario();
14102     overlay->setTrustedOverlay(false);
14103     // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
14104     ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
14105                          {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
14106                  ".* not a trusted overlay");
14107 }
14108 
TEST_F(InputDispatcherStylusInterceptorTest,ConsmesOnlyStylusEvents)14109 TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
14110     auto [overlay, window] = setupStylusOverlayScenario();
14111     mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
14112 
14113     sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
14114     overlay->consumeMotionDown();
14115     sendStylusEvent(AMOTION_EVENT_ACTION_UP);
14116     overlay->consumeMotionUp();
14117 
14118     sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
14119     window->consumeMotionDown();
14120     sendFingerEvent(AMOTION_EVENT_ACTION_UP);
14121     window->consumeMotionUp();
14122 
14123     overlay->assertNoEvents();
14124     window->assertNoEvents();
14125 }
14126 
TEST_F(InputDispatcherStylusInterceptorTest,SpyWindowStylusInterceptor)14127 TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
14128     auto [overlay, window] = setupStylusOverlayScenario();
14129     overlay->setSpy(true);
14130     mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
14131 
14132     sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
14133     overlay->consumeMotionDown();
14134     window->consumeMotionDown();
14135     sendStylusEvent(AMOTION_EVENT_ACTION_UP);
14136     overlay->consumeMotionUp();
14137     window->consumeMotionUp();
14138 
14139     sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
14140     window->consumeMotionDown();
14141     sendFingerEvent(AMOTION_EVENT_ACTION_UP);
14142     window->consumeMotionUp();
14143 
14144     overlay->assertNoEvents();
14145     window->assertNoEvents();
14146 }
14147 
14148 /**
14149  * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
14150  * The scenario is as follows:
14151  *   - The stylus interceptor overlay is configured as a spy window.
14152  *   - The stylus interceptor spy receives the start of a new stylus gesture.
14153  *   - It pilfers pointers and then configures itself to no longer be a spy.
14154  *   - The stylus interceptor continues to receive the rest of the gesture.
14155  */
TEST_F(InputDispatcherStylusInterceptorTest,StylusHandwritingScenario)14156 TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
14157     auto [overlay, window] = setupStylusOverlayScenario();
14158     overlay->setSpy(true);
14159     mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
14160 
14161     sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
14162     overlay->consumeMotionDown();
14163     window->consumeMotionDown();
14164 
14165     // The interceptor pilfers the pointers.
14166     EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
14167     window->consumeMotionCancel();
14168 
14169     // The interceptor configures itself so that it is no longer a spy.
14170     overlay->setSpy(false);
14171     mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
14172 
14173     // It continues to receive the rest of the stylus gesture.
14174     sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
14175     overlay->consumeMotionMove();
14176     sendStylusEvent(AMOTION_EVENT_ACTION_UP);
14177     overlay->consumeMotionUp();
14178 
14179     window->assertNoEvents();
14180 }
14181 
14182 struct User {
14183     gui::Pid mPid;
14184     gui::Uid mUid;
14185     uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
14186     std::unique_ptr<InputDispatcher>& mDispatcher;
14187 
Userandroid::inputdispatcher::User14188     User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
14189           : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
14190 
injectTargetedMotionandroid::inputdispatcher::User14191     InputEventInjectionResult injectTargetedMotion(int32_t action) const {
14192         return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
14193                                  ui::LogicalDisplayId::DEFAULT, {100, 200},
14194                                  {AMOTION_EVENT_INVALID_CURSOR_POSITION,
14195                                   AMOTION_EVENT_INVALID_CURSOR_POSITION},
14196                                  INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
14197                                  systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
14198     }
14199 
injectTargetedKeyandroid::inputdispatcher::User14200     InputEventInjectionResult injectTargetedKey(int32_t action) const {
14201         return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
14202                                           ui::LogicalDisplayId::INVALID,
14203                                           InputEventInjectionSync::WAIT_FOR_RESULT,
14204                                           INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
14205                                           mPolicyFlags);
14206     }
14207 
createWindowandroid::inputdispatcher::User14208     sp<FakeWindowHandle> createWindow(const char* name) const {
14209         std::shared_ptr<FakeApplicationHandle> overlayApplication =
14210                 std::make_shared<FakeApplicationHandle>();
14211         sp<FakeWindowHandle> window =
14212                 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
14213                                            ui::LogicalDisplayId::DEFAULT);
14214         window->setOwnerInfo(mPid, mUid);
14215         return window;
14216     }
14217 };
14218 
14219 using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
14220 
TEST_F(InputDispatcherTargetedInjectionTest,CanInjectIntoOwnedWindow)14221 TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
14222     auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
14223     auto window = owner.createWindow("Owned window");
14224     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
14225 
14226     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14227               owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14228     window->consumeMotionDown();
14229 
14230     setFocusedWindow(window);
14231     window->consumeFocusEvent(true);
14232 
14233     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14234               owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
14235     window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
14236 }
14237 
TEST_F(InputDispatcherTargetedInjectionTest,CannotInjectIntoUnownedWindow)14238 TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
14239     auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
14240     auto window = owner.createWindow("Owned window");
14241     mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
14242 
14243     auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
14244     EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
14245               rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14246 
14247     setFocusedWindow(window);
14248     window->consumeFocusEvent(true);
14249 
14250     EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
14251               rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
14252     window->assertNoEvents();
14253 }
14254 
TEST_F(InputDispatcherTargetedInjectionTest,CanInjectIntoOwnedSpyWindow)14255 TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
14256     auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
14257     auto window = owner.createWindow("Owned window");
14258     auto spy = owner.createWindow("Owned spy");
14259     spy->setSpy(true);
14260     spy->setTrustedOverlay(true);
14261     mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
14262 
14263     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14264               owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14265     spy->consumeMotionDown();
14266     window->consumeMotionDown();
14267 }
14268 
TEST_F(InputDispatcherTargetedInjectionTest,CannotInjectIntoUnownedSpyWindow)14269 TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
14270     auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
14271     auto window = owner.createWindow("Owned window");
14272 
14273     auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
14274     auto randosSpy = rando.createWindow("Rando's spy");
14275     randosSpy->setSpy(true);
14276     randosSpy->setTrustedOverlay(true);
14277     mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
14278 
14279     // The event is targeted at owner's window, so injection should succeed, but the spy should
14280     // not receive the event.
14281     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14282               owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14283     randosSpy->assertNoEvents();
14284     window->consumeMotionDown();
14285 }
14286 
TEST_F(InputDispatcherTargetedInjectionTest,CanInjectIntoAnyWindowWhenNotTargeting)14287 TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
14288     auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
14289     auto window = owner.createWindow("Owned window");
14290 
14291     auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
14292     auto randosSpy = rando.createWindow("Rando's spy");
14293     randosSpy->setSpy(true);
14294     randosSpy->setTrustedOverlay(true);
14295     mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
14296 
14297     // A user that has injection permission can inject into any window.
14298     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14299               injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
14300                                 ui::LogicalDisplayId::DEFAULT));
14301     randosSpy->consumeMotionDown();
14302     window->consumeMotionDown();
14303 
14304     setFocusedWindow(randosSpy);
14305     randosSpy->consumeFocusEvent(true);
14306 
14307     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
14308     randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
14309     window->assertNoEvents();
14310 }
14311 
TEST_F(InputDispatcherTargetedInjectionTest,CannotGenerateActionOutsideToOtherUids)14312 TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
14313     auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
14314     auto window = owner.createWindow("Owned window");
14315 
14316     auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
14317     auto randosWindow = rando.createWindow("Rando's window");
14318     randosWindow->setFrame(Rect{-10, -10, -5, -5});
14319     randosWindow->setWatchOutsideTouch(true);
14320     mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
14321 
14322     // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
14323     EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14324               owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14325     window->consumeMotionDown();
14326     randosWindow->assertNoEvents();
14327 }
14328 
14329 using InputDispatcherPointerInWindowTest = InputDispatcherTest;
14330 
TEST_F(InputDispatcherPointerInWindowTest,PointerInWindowWhenHovering)14331 TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
14332     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14333 
14334     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
14335                                                            ui::LogicalDisplayId::DEFAULT);
14336     left->setFrame(Rect(0, 0, 100, 100));
14337     sp<FakeWindowHandle> right =
14338             sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14339                                        ui::LogicalDisplayId::DEFAULT);
14340     right->setFrame(Rect(100, 0, 200, 100));
14341     sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
14342                                                           ui::LogicalDisplayId::DEFAULT);
14343     spy->setFrame(Rect(0, 0, 200, 100));
14344     spy->setTrustedOverlay(true);
14345     spy->setSpy(true);
14346 
14347     mDispatcher->onWindowInfosChanged(
14348             {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
14349 
14350     // Hover into the left window.
14351     mDispatcher->notifyMotion(
14352             MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
14353                     .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
14354                     .build());
14355 
14356     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14357     spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14358 
14359     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14360                                                DEVICE_ID,
14361                                                /*pointerId=*/0));
14362     ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14363                                                DEVICE_ID,
14364                                                /*pointerId=*/0));
14365     ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14366                                                 DEVICE_ID,
14367                                                 /*pointerId=*/0));
14368 
14369     // Hover move to the right window.
14370     mDispatcher->notifyMotion(
14371             MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
14372                     .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
14373                     .build());
14374 
14375     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14376     right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14377     spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
14378 
14379     ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14380                                                 DEVICE_ID,
14381                                                 /*pointerId=*/0));
14382     ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14383                                                DEVICE_ID,
14384                                                /*pointerId=*/0));
14385     ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14386                                                DEVICE_ID,
14387                                                /*pointerId=*/0));
14388 
14389     // Stop hovering.
14390     mDispatcher->notifyMotion(
14391             MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
14392                     .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
14393                     .build());
14394 
14395     right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14396     spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14397 
14398     ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14399                                                 DEVICE_ID,
14400                                                 /*pointerId=*/0));
14401     ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14402                                                 DEVICE_ID,
14403                                                 /*pointerId=*/0));
14404     ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14405                                                 DEVICE_ID,
14406                                                 /*pointerId=*/0));
14407 }
14408 
TEST_F(InputDispatcherPointerInWindowTest,PointerInWindowWithSplitTouch)14409 TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
14410     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14411 
14412     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
14413                                                            ui::LogicalDisplayId::DEFAULT);
14414     left->setFrame(Rect(0, 0, 100, 100));
14415     sp<FakeWindowHandle> right =
14416             sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14417                                        ui::LogicalDisplayId::DEFAULT);
14418     right->setFrame(Rect(100, 0, 200, 100));
14419     sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
14420                                                           ui::LogicalDisplayId::DEFAULT);
14421     spy->setFrame(Rect(0, 0, 200, 100));
14422     spy->setTrustedOverlay(true);
14423     spy->setSpy(true);
14424 
14425     mDispatcher->onWindowInfosChanged(
14426             {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
14427 
14428     // First pointer down on left window.
14429     mDispatcher->notifyMotion(
14430             MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14431                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14432                     .build());
14433 
14434     left->consumeMotionDown();
14435     spy->consumeMotionDown();
14436 
14437     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14438                                                DEVICE_ID,
14439                                                /*pointerId=*/0));
14440     ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14441                                                DEVICE_ID,
14442                                                /*pointerId=*/0));
14443     ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14444                                                 DEVICE_ID,
14445                                                 /*pointerId=*/0));
14446 
14447     // Second pointer down on right window.
14448     mDispatcher->notifyMotion(
14449             MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14450                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14451                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
14452                     .build());
14453 
14454     left->consumeMotionMove();
14455     right->consumeMotionDown();
14456     spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
14457 
14458     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14459                                                DEVICE_ID,
14460                                                /*pointerId=*/0));
14461     ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14462                                                DEVICE_ID,
14463                                                /*pointerId=*/0));
14464     ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14465                                                 DEVICE_ID,
14466                                                 /*pointerId=*/0));
14467     ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14468                                                 DEVICE_ID,
14469                                                 /*pointerId=*/1));
14470     ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14471                                                DEVICE_ID,
14472                                                /*pointerId=*/1));
14473     ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14474                                                DEVICE_ID,
14475                                                /*pointerId=*/1));
14476 
14477     // Second pointer up.
14478     mDispatcher->notifyMotion(
14479             MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
14480                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14481                     .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
14482                     .build());
14483 
14484     left->consumeMotionMove();
14485     right->consumeMotionUp();
14486     spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
14487 
14488     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14489                                                DEVICE_ID,
14490                                                /*pointerId=*/0));
14491     ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14492                                                DEVICE_ID,
14493                                                /*pointerId=*/0));
14494     ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14495                                                 DEVICE_ID,
14496                                                 /*pointerId=*/0));
14497     ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14498                                                 DEVICE_ID,
14499                                                 /*pointerId=*/1));
14500     ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14501                                                 DEVICE_ID,
14502                                                 /*pointerId=*/1));
14503     ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14504                                                 DEVICE_ID,
14505                                                 /*pointerId=*/1));
14506 
14507     // First pointer up.
14508     mDispatcher->notifyMotion(
14509             MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
14510                     .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14511                     .build());
14512 
14513     left->consumeMotionUp();
14514     spy->consumeMotionUp();
14515 
14516     ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14517                                                 DEVICE_ID,
14518                                                 /*pointerId=*/0));
14519     ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14520                                                 DEVICE_ID,
14521                                                 /*pointerId=*/0));
14522     ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14523                                                 DEVICE_ID,
14524                                                 /*pointerId=*/0));
14525 }
14526 
TEST_F(InputDispatcherPointerInWindowTest,MultipleDevicesControllingOneMouse_legacy)14527 TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
14528     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
14529     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14530 
14531     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
14532                                                            ui::LogicalDisplayId::DEFAULT);
14533     left->setFrame(Rect(0, 0, 100, 100));
14534     sp<FakeWindowHandle> right =
14535             sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14536                                        ui::LogicalDisplayId::DEFAULT);
14537     right->setFrame(Rect(100, 0, 200, 100));
14538 
14539     mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14540 
14541     ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14542                                                 DEVICE_ID,
14543                                                 /*pointerId=*/0));
14544     ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14545                                                 DEVICE_ID,
14546                                                 /*pointerId=*/0));
14547 
14548     // Hover move into the window.
14549     mDispatcher->notifyMotion(
14550             MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14551                     .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14552                     .rawXCursorPosition(50)
14553                     .rawYCursorPosition(50)
14554                     .deviceId(DEVICE_ID)
14555                     .build());
14556 
14557     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14558 
14559     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14560                                                DEVICE_ID,
14561                                                /*pointerId=*/0));
14562 
14563     // Move the mouse with another device. This cancels the hovering pointer from the first device.
14564     mDispatcher->notifyMotion(
14565             MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14566                     .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14567                     .rawXCursorPosition(51)
14568                     .rawYCursorPosition(50)
14569                     .deviceId(SECOND_DEVICE_ID)
14570                     .build());
14571 
14572     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14573     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14574 
14575     // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14576     // a HOVER_EXIT from the first device.
14577     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14578                                                DEVICE_ID,
14579                                                /*pointerId=*/0));
14580     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14581                                                SECOND_DEVICE_ID,
14582                                                /*pointerId=*/0));
14583 
14584     // Move the mouse outside the window. Document the current behavior, where the window does not
14585     // receive HOVER_EXIT even though the mouse left the window.
14586     mDispatcher->notifyMotion(
14587             MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14588                     .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14589                     .rawXCursorPosition(150)
14590                     .rawYCursorPosition(50)
14591                     .deviceId(SECOND_DEVICE_ID)
14592                     .build());
14593 
14594     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14595     right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14596     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14597                                                DEVICE_ID,
14598                                                /*pointerId=*/0));
14599     ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14600                                                 SECOND_DEVICE_ID,
14601                                                 /*pointerId=*/0));
14602 }
14603 
14604 /**
14605  * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
14606  * the same cursor, and therefore have a shared motion event stream.
14607  */
TEST_F(InputDispatcherPointerInWindowTest,MultipleDevicesControllingOneMouse)14608 TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
14609     SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
14610     std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14611 
14612     sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
14613                                                            ui::LogicalDisplayId::DEFAULT);
14614     left->setFrame(Rect(0, 0, 100, 100));
14615     sp<FakeWindowHandle> right =
14616             sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14617                                        ui::LogicalDisplayId::DEFAULT);
14618     right->setFrame(Rect(100, 0, 200, 100));
14619 
14620     mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14621 
14622     ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14623                                                 DEVICE_ID,
14624                                                 /*pointerId=*/0));
14625     ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14626                                                 DEVICE_ID,
14627                                                 /*pointerId=*/0));
14628 
14629     // Hover move into the window.
14630     mDispatcher->notifyMotion(
14631             MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14632                     .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14633                     .rawXCursorPosition(50)
14634                     .rawYCursorPosition(50)
14635                     .deviceId(DEVICE_ID)
14636                     .build());
14637 
14638     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14639 
14640     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14641                                                DEVICE_ID,
14642                                                /*pointerId=*/0));
14643 
14644     // Move the mouse with another device
14645     mDispatcher->notifyMotion(
14646             MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14647                     .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14648                     .rawXCursorPosition(51)
14649                     .rawYCursorPosition(50)
14650                     .deviceId(SECOND_DEVICE_ID)
14651                     .build());
14652     left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14653 
14654     // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14655     // a HOVER_EXIT from the first device.
14656     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14657                                                DEVICE_ID,
14658                                                /*pointerId=*/0));
14659     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14660                                                SECOND_DEVICE_ID,
14661                                                /*pointerId=*/0));
14662 
14663     // Move the mouse outside the window. Document the current behavior, where the window does not
14664     // receive HOVER_EXIT even though the mouse left the window.
14665     mDispatcher->notifyMotion(
14666             MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14667                     .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14668                     .rawXCursorPosition(150)
14669                     .rawYCursorPosition(50)
14670                     .deviceId(SECOND_DEVICE_ID)
14671                     .build());
14672 
14673     right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14674     ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14675                                                DEVICE_ID,
14676                                                /*pointerId=*/0));
14677     ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14678                                                 SECOND_DEVICE_ID,
14679                                                 /*pointerId=*/0));
14680 }
14681 
TEST_F(InputDispatcherTest,FocusedDisplayChangeIsNotified)14682 TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
14683     mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
14684     mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
14685 }
14686 
14687 } // namespace android::inputdispatcher
14688