xref: /aosp_15_r20/frameworks/native/services/inputflinger/tests/CursorInputMapper_test.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright 2023 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 "CursorInputMapper.h"
18 
19 #include <list>
20 #include <optional>
21 #include <string>
22 #include <tuple>
23 #include <variant>
24 
25 #include <android-base/logging.h>
26 #include <android_companion_virtualdevice_flags.h>
27 #include <com_android_input_flags.h>
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30 #include <input/DisplayViewport.h>
31 #include <input/InputEventLabels.h>
32 #include <linux/input-event-codes.h>
33 #include <linux/input.h>
34 #include <utils/Timers.h>
35 
36 #include "InputMapperTest.h"
37 #include "InputReaderBase.h"
38 #include "InterfaceMocks.h"
39 #include "NotifyArgs.h"
40 #include "TestEventMatchers.h"
41 #include "ui/Rotation.h"
42 
43 #define TAG "CursorInputMapper_test"
44 
45 namespace android {
46 
47 using testing::AllOf;
48 using testing::Return;
49 using testing::VariantWith;
50 constexpr auto ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
51 constexpr auto ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
52 constexpr auto ACTION_UP = AMOTION_EVENT_ACTION_UP;
53 constexpr auto BUTTON_PRESS = AMOTION_EVENT_ACTION_BUTTON_PRESS;
54 constexpr auto BUTTON_RELEASE = AMOTION_EVENT_ACTION_BUTTON_RELEASE;
55 constexpr auto HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
56 constexpr auto INVALID_CURSOR_POSITION = AMOTION_EVENT_INVALID_CURSOR_POSITION;
57 constexpr auto AXIS_X = AMOTION_EVENT_AXIS_X;
58 constexpr auto AXIS_Y = AMOTION_EVENT_AXIS_Y;
59 constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
60 constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID = ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
61 constexpr int32_t DISPLAY_WIDTH = 480;
62 constexpr int32_t DISPLAY_HEIGHT = 800;
63 
64 constexpr int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
65 
66 namespace {
67 
createPrimaryViewport(ui::Rotation orientation)68 DisplayViewport createPrimaryViewport(ui::Rotation orientation) {
69     const bool isRotated =
70             orientation == ui::Rotation::Rotation90 || orientation == ui::Rotation::Rotation270;
71     DisplayViewport v;
72     v.displayId = DISPLAY_ID;
73     v.orientation = orientation;
74     v.logicalRight = isRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
75     v.logicalBottom = isRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
76     v.physicalRight = isRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
77     v.physicalBottom = isRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
78     v.deviceWidth = isRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
79     v.deviceHeight = isRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
80     v.isActive = true;
81     v.uniqueId = "local:1";
82     return v;
83 }
84 
createSecondaryViewport()85 DisplayViewport createSecondaryViewport() {
86     DisplayViewport v;
87     v.displayId = SECONDARY_DISPLAY_ID;
88     v.orientation = ui::Rotation::Rotation0;
89     v.logicalRight = DISPLAY_HEIGHT;
90     v.logicalBottom = DISPLAY_WIDTH;
91     v.physicalRight = DISPLAY_HEIGHT;
92     v.physicalBottom = DISPLAY_WIDTH;
93     v.deviceWidth = DISPLAY_HEIGHT;
94     v.deviceHeight = DISPLAY_WIDTH;
95     v.isActive = true;
96     v.uniqueId = "local:2";
97     v.type = ViewportType::EXTERNAL;
98     return v;
99 }
100 
101 // In a number of these tests, we want to check that some pointer motion is reported without
102 // specifying an exact value, as that would require updating the tests every time the pointer
103 // ballistics was changed. To do this, we make some matchers that only check the sign of a
104 // particular axis.
105 MATCHER_P(WithPositiveAxis, axis, "MotionEvent with a positive axis value") {
106     *result_listener << "expected 1 pointer with a positive "
107                      << InputEventLookup::getAxisLabel(axis) << " axis but got "
108                      << arg.pointerCoords.size() << " pointers, with axis value "
109                      << arg.pointerCoords[0].getAxisValue(axis);
110     return arg.pointerCoords.size() == 1 && arg.pointerCoords[0].getAxisValue(axis) > 0;
111 }
112 
113 MATCHER_P(WithZeroAxis, axis, "MotionEvent with a zero axis value") {
114     *result_listener << "expected 1 pointer with a zero " << InputEventLookup::getAxisLabel(axis)
115                      << " axis but got " << arg.pointerCoords.size()
116                      << " pointers, with axis value " << arg.pointerCoords[0].getAxisValue(axis);
117     return arg.pointerCoords.size() == 1 && arg.pointerCoords[0].getAxisValue(axis) == 0;
118 }
119 
120 MATCHER_P(WithNegativeAxis, axis, "MotionEvent with a negative axis value") {
121     *result_listener << "expected 1 pointer with a negative "
122                      << InputEventLookup::getAxisLabel(axis) << " axis but got "
123                      << arg.pointerCoords.size() << " pointers, with axis value "
124                      << arg.pointerCoords[0].getAxisValue(axis);
125     return arg.pointerCoords.size() == 1 && arg.pointerCoords[0].getAxisValue(axis) < 0;
126 }
127 
128 } // namespace
129 
130 namespace vd_flags = android::companion::virtualdevice::flags;
131 
132 /**
133  * Unit tests for CursorInputMapper.
134  * These classes are named 'CursorInputMapperUnitTest...' to avoid name collision with the existing
135  * 'CursorInputMapperTest...' classes. If all of the CursorInputMapper tests are migrated here, the
136  * name can be simplified to 'CursorInputMapperTest'.
137  *
138  * TODO(b/283812079): move the remaining CursorInputMapper tests here. The ones that are left all
139  *   depend on viewport association, for which we'll need to fake InputDeviceContext.
140  */
141 class CursorInputMapperUnitTestBase : public InputMapperUnitTest {
142 protected:
SetUp()143     void SetUp() override { SetUpWithBus(BUS_USB); }
SetUpWithBus(int bus)144     void SetUpWithBus(int bus) override {
145         InputMapperUnitTest::SetUpWithBus(bus);
146 
147         // Current scan code state - all keys are UP by default
148         setScanCodeState(KeyState::UP,
149                          {BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, BTN_BACK, BTN_SIDE, BTN_FORWARD,
150                           BTN_EXTRA, BTN_TASK});
151         EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL))
152                 .WillRepeatedly(Return(false));
153         EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL))
154                 .WillRepeatedly(Return(false));
155         EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES))
156                 .WillRepeatedly(Return(false));
157         EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES))
158                 .WillRepeatedly(Return(false));
159 
160         mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
161         mFakePolicy->addDisplayViewport(createPrimaryViewport(ui::Rotation::Rotation0));
162     }
163 
createMapper()164     void createMapper() {
165         mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
166     }
167 
setPointerCapture(bool enabled)168     void setPointerCapture(bool enabled) {
169         mReaderConfiguration.pointerCaptureRequest.window = enabled ? sp<BBinder>::make() : nullptr;
170         mReaderConfiguration.pointerCaptureRequest.seq = 1;
171         int32_t generation = mDevice->getGeneration();
172         std::list<NotifyArgs> args =
173                 mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
174                                      InputReaderConfiguration::Change::POINTER_CAPTURE);
175         ASSERT_THAT(args,
176                     ElementsAre(VariantWith<NotifyDeviceResetArgs>(
177                             AllOf(WithDeviceId(DEVICE_ID), WithEventTime(ARBITRARY_TIME)))));
178 
179         // Check that generation also got bumped
180         ASSERT_GT(mDevice->getGeneration(), generation);
181     }
182 
testRotation(int32_t originalX,int32_t originalY,const testing::Matcher<NotifyMotionArgs> & coordsMatcher)183     void testRotation(int32_t originalX, int32_t originalY,
184                       const testing::Matcher<NotifyMotionArgs>& coordsMatcher) {
185         std::list<NotifyArgs> args;
186         args += process(ARBITRARY_TIME, EV_REL, REL_X, originalX);
187         args += process(ARBITRARY_TIME, EV_REL, REL_Y, originalY);
188         args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
189         ASSERT_THAT(args,
190                     ElementsAre(VariantWith<NotifyMotionArgs>(
191                             AllOf(WithMotionAction(ACTION_MOVE), coordsMatcher))));
192     }
193 };
194 
195 class CursorInputMapperUnitTest : public CursorInputMapperUnitTestBase {
196 protected:
SetUp()197     void SetUp() override {
198         vd_flags::high_resolution_scroll(false);
199         CursorInputMapperUnitTestBase::SetUp();
200     }
201 };
202 
TEST_F(CursorInputMapperUnitTest,GetSourcesReturnsMouseInPointerMode)203 TEST_F(CursorInputMapperUnitTest, GetSourcesReturnsMouseInPointerMode) {
204     mPropertyMap.addProperty("cursor.mode", "pointer");
205     createMapper();
206 
207     ASSERT_EQ(AINPUT_SOURCE_MOUSE, mMapper->getSources());
208 }
209 
TEST_F(CursorInputMapperUnitTest,GetSourcesReturnsTrackballInNavigationMode)210 TEST_F(CursorInputMapperUnitTest, GetSourcesReturnsTrackballInNavigationMode) {
211     mPropertyMap.addProperty("cursor.mode", "navigation");
212     createMapper();
213 
214     ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mMapper->getSources());
215 }
216 
217 /**
218  * Move the mouse and then click the button. Check whether HOVER_EXIT is generated when hovering
219  * ends. Currently, it is not.
220  */
TEST_F(CursorInputMapperUnitTest,HoverAndLeftButtonPress)221 TEST_F(CursorInputMapperUnitTest, HoverAndLeftButtonPress) {
222     createMapper();
223     std::list<NotifyArgs> args;
224 
225     // Move the cursor a little
226     args += process(EV_REL, REL_X, 10);
227     args += process(EV_REL, REL_Y, 20);
228     args += process(EV_SYN, SYN_REPORT, 0);
229     ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
230 
231     // Now click the mouse button
232     args.clear();
233     args += process(EV_KEY, BTN_LEFT, 1);
234     args += process(EV_SYN, SYN_REPORT, 0);
235 
236     ASSERT_THAT(args,
237                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
238                             VariantWith<NotifyMotionArgs>(
239                                     AllOf(WithMotionAction(BUTTON_PRESS),
240                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY)))));
241     ASSERT_THAT(args,
242                 Each(VariantWith<NotifyMotionArgs>(WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY))));
243 
244     // Move some more.
245     args.clear();
246     args += process(EV_REL, REL_X, 10);
247     args += process(EV_REL, REL_Y, 20);
248     args += process(EV_SYN, SYN_REPORT, 0);
249     ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_MOVE))));
250 
251     // Release the button
252     args.clear();
253     args += process(EV_KEY, BTN_LEFT, 0);
254     args += process(EV_SYN, SYN_REPORT, 0);
255     ASSERT_THAT(args,
256                 ElementsAre(VariantWith<NotifyMotionArgs>(
257                                     AllOf(WithMotionAction(BUTTON_RELEASE),
258                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY))),
259                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
260                             VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
261 }
262 
263 /**
264  * Test that enabling mouse swap primary button will have the left click result in a
265  * `SECONDARY_BUTTON` event and a right click will result in a `PRIMARY_BUTTON` event.
266  */
TEST_F(CursorInputMapperUnitTest,SwappedPrimaryButtonPress)267 TEST_F(CursorInputMapperUnitTest, SwappedPrimaryButtonPress) {
268     mReaderConfiguration.mouseSwapPrimaryButtonEnabled = true;
269     createMapper();
270     std::list<NotifyArgs> args;
271 
272     // Now click the left mouse button , expect a `SECONDARY_BUTTON` button state.
273     args.clear();
274     args += process(EV_KEY, BTN_LEFT, 1);
275     args += process(EV_SYN, SYN_REPORT, 0);
276 
277     ASSERT_THAT(args,
278                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
279                             VariantWith<NotifyMotionArgs>(
280                                     AllOf(WithMotionAction(BUTTON_PRESS),
281                                           WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY)))));
282     ASSERT_THAT(args,
283                 Each(VariantWith<NotifyMotionArgs>(
284                         WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY))));
285 
286     // Release the left button.
287     args.clear();
288     args += process(EV_KEY, BTN_LEFT, 0);
289     args += process(EV_SYN, SYN_REPORT, 0);
290 
291     ASSERT_THAT(args,
292                 ElementsAre(VariantWith<NotifyMotionArgs>(
293                                     AllOf(WithMotionAction(BUTTON_RELEASE),
294                                           WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY))),
295                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
296                             VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
297 
298     // Now click the right mouse button , expect a `PRIMARY_BUTTON` button state.
299     args.clear();
300     args += process(EV_KEY, BTN_RIGHT, 1);
301     args += process(EV_SYN, SYN_REPORT, 0);
302 
303     ASSERT_THAT(args,
304                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
305                             VariantWith<NotifyMotionArgs>(
306                                     AllOf(WithMotionAction(BUTTON_PRESS),
307                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY)))));
308     ASSERT_THAT(args,
309                 Each(VariantWith<NotifyMotionArgs>(WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY))));
310 
311     // Release the right button.
312     args.clear();
313     args += process(EV_KEY, BTN_RIGHT, 0);
314     args += process(EV_SYN, SYN_REPORT, 0);
315     ASSERT_THAT(args,
316                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
317                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
318                             VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
319 
320     ASSERT_THAT(args,
321                 ElementsAre(VariantWith<NotifyMotionArgs>(
322                                     AllOf(WithMotionAction(BUTTON_RELEASE),
323                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY))),
324                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
325                             VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
326 }
327 
328 /**
329  * Set pointer capture and check that ACTION_MOVE events are emitted from CursorInputMapper.
330  * During pointer capture, source should be set to MOUSE_RELATIVE. When the capture is disabled,
331  * the events should be generated normally:
332  *   1) The source should return to SOURCE_MOUSE
333  *   2) Cursor position should be incremented by the relative device movements
334  *   3) Cursor position of NotifyMotionArgs should now be getting populated.
335  * When it's not SOURCE_MOUSE, CursorInputMapper doesn't populate cursor position values.
336  */
TEST_F(CursorInputMapperUnitTest,ProcessPointerCapture)337 TEST_F(CursorInputMapperUnitTest, ProcessPointerCapture) {
338     createMapper();
339     setPointerCapture(true);
340     std::list<NotifyArgs> args;
341 
342     // Move.
343     args += process(EV_REL, REL_X, 10);
344     args += process(EV_REL, REL_Y, 20);
345     args += process(EV_SYN, SYN_REPORT, 0);
346 
347     ASSERT_THAT(args,
348                 ElementsAre(VariantWith<NotifyMotionArgs>(
349                         AllOf(WithMotionAction(ACTION_MOVE),
350                               WithSource(AINPUT_SOURCE_MOUSE_RELATIVE), WithCoords(10.0f, 20.0f),
351                               WithRelativeMotion(10.0f, 20.0f),
352                               WithCursorPosition(INVALID_CURSOR_POSITION,
353                                                  INVALID_CURSOR_POSITION)))));
354 
355     // Button press.
356     args.clear();
357     args += process(EV_KEY, BTN_MOUSE, 1);
358     args += process(EV_SYN, SYN_REPORT, 0);
359     ASSERT_THAT(args,
360                 ElementsAre(VariantWith<NotifyMotionArgs>(
361                                     AllOf(WithMotionAction(ACTION_DOWN),
362                                           WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
363                                           WithCoords(0.0f, 0.0f), WithPressure(1.0f))),
364                             VariantWith<NotifyMotionArgs>(
365                                     AllOf(WithMotionAction(BUTTON_PRESS),
366                                           WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
367                                           WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
368 
369     // Button release.
370     args.clear();
371     args += process(EV_KEY, BTN_MOUSE, 0);
372     args += process(EV_SYN, SYN_REPORT, 0);
373     ASSERT_THAT(args,
374                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
375                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP))));
376     ASSERT_THAT(args,
377                 Each(VariantWith<NotifyMotionArgs>(AllOf(WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
378                                                          WithCoords(0.0f, 0.0f),
379                                                          WithPressure(0.0f)))));
380 
381     // Another move.
382     args.clear();
383     args += process(EV_REL, REL_X, 30);
384     args += process(EV_REL, REL_Y, 40);
385     args += process(EV_SYN, SYN_REPORT, 0);
386     ASSERT_THAT(args,
387                 ElementsAre(VariantWith<NotifyMotionArgs>(
388                         AllOf(WithMotionAction(ACTION_MOVE),
389                               WithSource(AINPUT_SOURCE_MOUSE_RELATIVE), WithCoords(30.0f, 40.0f),
390                               WithRelativeMotion(30.0f, 40.0f)))));
391 
392     // Disable pointer capture. Afterwards, events should be generated the usual way.
393     setPointerCapture(false);
394     const auto expectedCoords = WithCoords(0, 0);
395     const auto expectedCursorPosition =
396             WithCursorPosition(INVALID_CURSOR_POSITION, INVALID_CURSOR_POSITION);
397     args.clear();
398     args += process(EV_REL, REL_X, 10);
399     args += process(EV_REL, REL_Y, 20);
400     args += process(EV_SYN, SYN_REPORT, 0);
401     ASSERT_THAT(args,
402                 ElementsAre(VariantWith<NotifyMotionArgs>(
403                         AllOf(WithMotionAction(HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
404                               expectedCoords, expectedCursorPosition,
405                               WithPositiveAxis(AMOTION_EVENT_AXIS_RELATIVE_X),
406                               WithPositiveAxis(AMOTION_EVENT_AXIS_RELATIVE_Y)))));
407 }
408 
TEST_F(CursorInputMapperUnitTest,PopulateDeviceInfoReturnsScaledRangeInNavigationMode)409 TEST_F(CursorInputMapperUnitTest, PopulateDeviceInfoReturnsScaledRangeInNavigationMode) {
410     mPropertyMap.addProperty("cursor.mode", "navigation");
411     createMapper();
412 
413     InputDeviceInfo info;
414     mMapper->populateDeviceInfo(info);
415 
416     ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_TRACKBALL,
417                                               -1.0f, 1.0f, 0.0f,
418                                               1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
419     ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_TRACKBALL,
420                                               -1.0f, 1.0f, 0.0f,
421                                               1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
422     ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE,
423                                               AINPUT_SOURCE_TRACKBALL, 0.0f, 1.0f, 0.0f, 0.0f));
424 }
425 
TEST_F(CursorInputMapperUnitTest,ProcessShouldSetAllFieldsAndIncludeGlobalMetaState)426 TEST_F(CursorInputMapperUnitTest, ProcessShouldSetAllFieldsAndIncludeGlobalMetaState) {
427     mPropertyMap.addProperty("cursor.mode", "navigation");
428     createMapper();
429 
430     EXPECT_CALL(mMockInputReaderContext, getGlobalMetaState())
431             .WillRepeatedly(Return(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON));
432 
433     std::list<NotifyArgs> args;
434 
435     // Button press.
436     // Mostly testing non x/y behavior here so we don't need to check again elsewhere.
437     args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
438     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
439     EXPECT_THAT(args,
440                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
441                             VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS))));
442     EXPECT_THAT(args,
443                 Each(VariantWith<NotifyMotionArgs>(
444                         AllOf(WithEventTime(ARBITRARY_TIME), WithDeviceId(DEVICE_ID),
445                               WithSource(AINPUT_SOURCE_TRACKBALL), WithFlags(0), WithEdgeFlags(0),
446                               WithPolicyFlags(0),
447                               WithMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON),
448                               WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY), WithPointerCount(1),
449                               WithPointerId(0, 0), WithToolType(ToolType::MOUSE),
450                               WithCoords(0.0f, 0.0f), WithPressure(1.0f),
451                               WithPrecision(TRACKBALL_MOVEMENT_THRESHOLD,
452                                             TRACKBALL_MOVEMENT_THRESHOLD),
453                               WithDownTime(ARBITRARY_TIME)))));
454     args.clear();
455 
456     // Button release.  Should have same down time.
457     args += process(ARBITRARY_TIME + 1, EV_KEY, BTN_MOUSE, 0);
458     args += process(ARBITRARY_TIME + 1, EV_SYN, SYN_REPORT, 0);
459     EXPECT_THAT(args,
460                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
461                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP))));
462     EXPECT_THAT(args,
463                 Each(VariantWith<NotifyMotionArgs>(
464                         AllOf(WithEventTime(ARBITRARY_TIME + 1), WithDeviceId(DEVICE_ID),
465                               WithSource(AINPUT_SOURCE_TRACKBALL), WithFlags(0), WithEdgeFlags(0),
466                               WithPolicyFlags(0),
467                               WithMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON),
468                               WithButtonState(0), WithPointerCount(1), WithPointerId(0, 0),
469                               WithToolType(ToolType::MOUSE), WithCoords(0.0f, 0.0f),
470                               WithPressure(0.0f),
471                               WithPrecision(TRACKBALL_MOVEMENT_THRESHOLD,
472                                             TRACKBALL_MOVEMENT_THRESHOLD),
473                               WithDownTime(ARBITRARY_TIME)))));
474 }
475 
TEST_F(CursorInputMapperUnitTest,ProcessShouldHandleIndependentXYUpdates)476 TEST_F(CursorInputMapperUnitTest, ProcessShouldHandleIndependentXYUpdates) {
477     mPropertyMap.addProperty("cursor.mode", "navigation");
478     createMapper();
479 
480     std::list<NotifyArgs> args;
481 
482     // Motion in X but not Y.
483     args += process(ARBITRARY_TIME, EV_REL, REL_X, 1);
484     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
485     EXPECT_THAT(args,
486                 ElementsAre(VariantWith<NotifyMotionArgs>(
487                         AllOf(WithMotionAction(ACTION_MOVE), WithPressure(0.0f),
488                               WithPositiveAxis(AXIS_X), WithZeroAxis(AXIS_Y)))));
489     args.clear();
490 
491     // Motion in Y but not X.
492     args += process(ARBITRARY_TIME, EV_REL, REL_Y, -2);
493     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
494     EXPECT_THAT(args,
495                 ElementsAre(VariantWith<NotifyMotionArgs>(
496                         AllOf(WithMotionAction(ACTION_MOVE), WithPressure(0.0f),
497                               WithZeroAxis(AXIS_X), WithNegativeAxis(AXIS_Y)))));
498     args.clear();
499 }
500 
TEST_F(CursorInputMapperUnitTest,ProcessShouldHandleIndependentButtonUpdates)501 TEST_F(CursorInputMapperUnitTest, ProcessShouldHandleIndependentButtonUpdates) {
502     mPropertyMap.addProperty("cursor.mode", "navigation");
503     createMapper();
504 
505     std::list<NotifyArgs> args;
506 
507     // Button press.
508     args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
509     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
510     EXPECT_THAT(args,
511                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
512                             VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS))));
513     EXPECT_THAT(args,
514                 Each(VariantWith<NotifyMotionArgs>(
515                         AllOf(WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
516     args.clear();
517 
518     // Button release.
519     args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 0);
520     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
521     EXPECT_THAT(args,
522                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
523                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP))));
524     EXPECT_THAT(args,
525                 Each(VariantWith<NotifyMotionArgs>(
526                         AllOf(WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
527 }
528 
TEST_F(CursorInputMapperUnitTest,ProcessShouldHandleCombinedXYAndButtonUpdates)529 TEST_F(CursorInputMapperUnitTest, ProcessShouldHandleCombinedXYAndButtonUpdates) {
530     mPropertyMap.addProperty("cursor.mode", "navigation");
531     createMapper();
532 
533     std::list<NotifyArgs> args;
534 
535     // Combined X, Y and Button.
536     args += process(ARBITRARY_TIME, EV_REL, REL_X, 1);
537     args += process(ARBITRARY_TIME, EV_REL, REL_Y, -2);
538     args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
539     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
540     EXPECT_THAT(args,
541                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
542                             VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS))));
543     EXPECT_THAT(args,
544                 Each(VariantWith<NotifyMotionArgs>(AllOf(WithPositiveAxis(AXIS_X),
545                                                          WithNegativeAxis(AXIS_Y),
546                                                          WithPressure(1.0f)))));
547     args.clear();
548 
549     // Move X, Y a bit while pressed.
550     args += process(ARBITRARY_TIME, EV_REL, REL_X, 2);
551     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 1);
552     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
553     EXPECT_THAT(args,
554                 ElementsAre(VariantWith<NotifyMotionArgs>(
555                         AllOf(WithMotionAction(ACTION_MOVE), WithPressure(1.0f),
556                               WithPositiveAxis(AXIS_X), WithPositiveAxis(AXIS_Y)))));
557     args.clear();
558 
559     // Release Button.
560     args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 0);
561     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
562     EXPECT_THAT(args,
563                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
564                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP))));
565     EXPECT_THAT(args,
566                 Each(VariantWith<NotifyMotionArgs>(
567                         AllOf(WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
568     args.clear();
569 }
570 
TEST_F(CursorInputMapperUnitTest,ProcessShouldNotRotateMotionsWhenOrientationAware)571 TEST_F(CursorInputMapperUnitTest, ProcessShouldNotRotateMotionsWhenOrientationAware) {
572     // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
573     // need to be rotated.
574     mPropertyMap.addProperty("cursor.mode", "navigation");
575     mPropertyMap.addProperty("cursor.orientationAware", "1");
576     EXPECT_CALL((*mDevice), getAssociatedViewport)
577             .WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation90)));
578     mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
579 
580     constexpr auto X = AXIS_X;
581     constexpr auto Y = AXIS_Y;
582     ASSERT_NO_FATAL_FAILURE(testRotation( 0,  1, AllOf(WithZeroAxis(X),     WithPositiveAxis(Y))));
583     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
584     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  0, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
585     ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
586     ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithZeroAxis(X),     WithNegativeAxis(Y))));
587     ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
588     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  0, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
589     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
590 }
591 
TEST_F(CursorInputMapperUnitTest,ProcessShouldRotateMotionsWhenNotOrientationAware)592 TEST_F(CursorInputMapperUnitTest, ProcessShouldRotateMotionsWhenNotOrientationAware) {
593     // Since InputReader works in the un-rotated coordinate space, only devices that are not
594     // orientation-aware are affected by display rotation.
595     mPropertyMap.addProperty("cursor.mode", "navigation");
596     EXPECT_CALL((*mDevice), getAssociatedViewport)
597             .WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation0)));
598     mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
599 
600     constexpr auto X = AXIS_X;
601     constexpr auto Y = AXIS_Y;
602     ASSERT_NO_FATAL_FAILURE(testRotation( 0,  1, AllOf(WithZeroAxis(X),     WithPositiveAxis(Y))));
603     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
604     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  0, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
605     ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
606     ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithZeroAxis(X),     WithNegativeAxis(Y))));
607     ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
608     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  0, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
609     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
610 
611     EXPECT_CALL((*mDevice), getAssociatedViewport)
612             .WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation90)));
613     std::list<NotifyArgs> args =
614             mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
615                                  InputReaderConfiguration::Change::DISPLAY_INFO);
616     ASSERT_NO_FATAL_FAILURE(testRotation( 0,  1, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
617     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
618     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  0, AllOf(WithZeroAxis(X),     WithPositiveAxis(Y))));
619     ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
620     ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
621     ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
622     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  0, AllOf(WithZeroAxis(X),     WithNegativeAxis(Y))));
623     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
624 
625     EXPECT_CALL((*mDevice), getAssociatedViewport)
626             .WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation180)));
627     args = mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
628                                 InputReaderConfiguration::Change::DISPLAY_INFO);
629     ASSERT_NO_FATAL_FAILURE(testRotation( 0,  1, AllOf(WithZeroAxis(X),     WithNegativeAxis(Y))));
630     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
631     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  0, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
632     ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
633     ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithZeroAxis(X),     WithPositiveAxis(Y))));
634     ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
635     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  0, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
636     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
637 
638     EXPECT_CALL((*mDevice), getAssociatedViewport)
639             .WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation270)));
640     args = mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
641                                 InputReaderConfiguration::Change::DISPLAY_INFO);
642     ASSERT_NO_FATAL_FAILURE(testRotation( 0,  1, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
643     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
644     ASSERT_NO_FATAL_FAILURE(testRotation( 1,  0, AllOf(WithZeroAxis(X),     WithNegativeAxis(Y))));
645     ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
646     ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
647     ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
648     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  0, AllOf(WithZeroAxis(X),     WithPositiveAxis(Y))));
649     ASSERT_NO_FATAL_FAILURE(testRotation(-1,  1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
650 }
651 
TEST_F(CursorInputMapperUnitTest,PopulateDeviceInfoReturnsRangeFromPolicy)652 TEST_F(CursorInputMapperUnitTest, PopulateDeviceInfoReturnsRangeFromPolicy) {
653     mPropertyMap.addProperty("cursor.mode", "pointer");
654     mFakePolicy->clearViewports();
655     createMapper();
656 
657     InputDeviceInfo info;
658     mMapper->populateDeviceInfo(info);
659 
660     // Initially there should not be a valid motion range because there's no viewport or pointer
661     // bounds.
662     ASSERT_EQ(nullptr, info.getMotionRange(AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE));
663     ASSERT_EQ(nullptr, info.getMotionRange(AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE));
664     ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE,
665                                               AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f));
666 
667     // When the viewport and the default pointer display ID is set, then there should be a valid
668     // motion range.
669     mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
670     mFakePolicy->addDisplayViewport(createPrimaryViewport(ui::Rotation::Rotation0));
671     std::list<NotifyArgs> args =
672             mMapper->reconfigure(systemTime(), mReaderConfiguration,
673                                  InputReaderConfiguration::Change::DISPLAY_INFO);
674     ASSERT_THAT(args, testing::IsEmpty());
675 
676     InputDeviceInfo info2;
677     mMapper->populateDeviceInfo(info2);
678 
679     ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE, 0,
680                                               DISPLAY_WIDTH - 1, 0.0f, 0.0f));
681     ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE, 0,
682                                               DISPLAY_HEIGHT - 1, 0.0f, 0.0f));
683     ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_PRESSURE,
684                                               AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f));
685 }
686 
TEST_F(CursorInputMapperUnitTest,ConfigureDisplayIdWithAssociatedViewport)687 TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdWithAssociatedViewport) {
688     DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation90);
689     DisplayViewport secondaryViewport = createSecondaryViewport();
690     mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport});
691     // Set up the secondary display as the display on which the pointer should be shown.
692     // The InputDevice is not associated with any display.
693     EXPECT_CALL((*mDevice), getAssociatedViewport).WillRepeatedly(Return(secondaryViewport));
694     mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
695 
696     std::list<NotifyArgs> args;
697     // Ensure input events are generated for the secondary display.
698     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
699     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
700     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
701     ASSERT_THAT(args,
702                 ElementsAre(VariantWith<NotifyMotionArgs>(
703                         AllOf(WithMotionAction(HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
704                               WithDisplayId(SECONDARY_DISPLAY_ID), WithCoords(0.0f, 0.0f)))));
705 }
706 
TEST_F(CursorInputMapperUnitTest,ConfigureDisplayIdShouldGenerateEventForMismatchedPointerDisplay)707 TEST_F(CursorInputMapperUnitTest,
708        ConfigureDisplayIdShouldGenerateEventForMismatchedPointerDisplay) {
709     DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation90);
710     DisplayViewport secondaryViewport = createSecondaryViewport();
711     mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport});
712     // Set up the primary display as the display on which the pointer should be shown.
713     // Associate the InputDevice with the secondary display.
714     EXPECT_CALL((*mDevice), getAssociatedViewport).WillRepeatedly(Return(secondaryViewport));
715     mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
716 
717     // With PointerChoreographer enabled, there could be a PointerController for the associated
718     // display even if it is different from the pointer display. So the mapper should generate an
719     // event.
720     std::list<NotifyArgs> args;
721     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
722     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
723     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
724     ASSERT_THAT(args,
725                 ElementsAre(VariantWith<NotifyMotionArgs>(
726                         AllOf(WithMotionAction(HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
727                               WithDisplayId(SECONDARY_DISPLAY_ID), WithCoords(0.0f, 0.0f)))));
728 }
729 
TEST_F(CursorInputMapperUnitTest,ProcessShouldHandleAllButtonsWithZeroCoords)730 TEST_F(CursorInputMapperUnitTest, ProcessShouldHandleAllButtonsWithZeroCoords) {
731     mPropertyMap.addProperty("cursor.mode", "pointer");
732     createMapper();
733 
734     std::list<NotifyArgs> args;
735 
736     // press BTN_LEFT, release BTN_LEFT
737     args += process(ARBITRARY_TIME, EV_KEY, BTN_LEFT, 1);
738     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
739     EXPECT_THAT(args,
740                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
741                             VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS))));
742     EXPECT_THAT(args,
743                 Each(VariantWith<NotifyMotionArgs>(
744                         AllOf(WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY), WithCoords(0.0f, 0.0f),
745                               WithPressure(1.0f)))));
746     args.clear();
747     args += process(ARBITRARY_TIME, EV_KEY, BTN_LEFT, 0);
748     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
749     EXPECT_THAT(args,
750                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
751                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
752                             VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
753     EXPECT_THAT(args,
754                 Each(VariantWith<NotifyMotionArgs>(
755                         AllOf(WithButtonState(0), WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
756     args.clear();
757 
758     // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
759     args += process(ARBITRARY_TIME, EV_KEY, BTN_RIGHT, 1);
760     args += process(ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 1);
761     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
762     EXPECT_THAT(args,
763                 ElementsAre(VariantWith<NotifyMotionArgs>(
764                                     AllOf(WithMotionAction(ACTION_DOWN),
765                                           WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY |
766                                                           AMOTION_EVENT_BUTTON_TERTIARY))),
767                             VariantWith<NotifyMotionArgs>(
768                                     AllOf(WithMotionAction(BUTTON_PRESS),
769                                           WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY))),
770                             VariantWith<NotifyMotionArgs>(
771                                     AllOf(WithMotionAction(BUTTON_PRESS),
772                                           WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY |
773                                                           AMOTION_EVENT_BUTTON_TERTIARY)))));
774     EXPECT_THAT(args,
775                 Each(VariantWith<NotifyMotionArgs>(
776                         AllOf(WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
777     args.clear();
778 
779     args += process(ARBITRARY_TIME, EV_KEY, BTN_RIGHT, 0);
780     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
781     EXPECT_THAT(args,
782                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
783                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_MOVE))));
784     EXPECT_THAT(args,
785                 Each(VariantWith<NotifyMotionArgs>(
786                         AllOf(WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY),
787                               WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
788     args.clear();
789 
790     args += process(ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 0);
791     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
792     EXPECT_THAT(args,
793                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
794                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
795                             VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
796     EXPECT_THAT(args,
797                 Each(VariantWith<NotifyMotionArgs>(
798                         AllOf(WithButtonState(0), WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
799 }
800 
801 class CursorInputMapperButtonKeyTest
802       : public CursorInputMapperUnitTest,
803         public testing::WithParamInterface<
804                 std::tuple<int32_t /*evdevCode*/, int32_t /*expectedButtonState*/,
805                            int32_t /*expectedKeyCode*/>> {};
806 
TEST_P(CursorInputMapperButtonKeyTest,ProcessShouldHandleButtonKeyWithZeroCoords)807 TEST_P(CursorInputMapperButtonKeyTest, ProcessShouldHandleButtonKeyWithZeroCoords) {
808     auto [evdevCode, expectedButtonState, expectedKeyCode] = GetParam();
809     mPropertyMap.addProperty("cursor.mode", "pointer");
810     createMapper();
811 
812     std::list<NotifyArgs> args;
813 
814     args += process(ARBITRARY_TIME, EV_KEY, evdevCode, 1);
815     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
816     EXPECT_THAT(args,
817                 ElementsAre(VariantWith<NotifyKeyArgs>(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
818                                                              WithKeyCode(expectedKeyCode))),
819                             VariantWith<NotifyMotionArgs>(
820                                     AllOf(WithMotionAction(HOVER_MOVE),
821                                           WithButtonState(expectedButtonState),
822                                           WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
823                             VariantWith<NotifyMotionArgs>(
824                                     AllOf(WithMotionAction(BUTTON_PRESS),
825                                           WithButtonState(expectedButtonState),
826                                           WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
827     args.clear();
828 
829     args += process(ARBITRARY_TIME, EV_KEY, evdevCode, 0);
830     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
831     EXPECT_THAT(args,
832                 ElementsAre(VariantWith<NotifyMotionArgs>(
833                                     AllOf(WithMotionAction(BUTTON_RELEASE), WithButtonState(0),
834                                           WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
835                             VariantWith<NotifyMotionArgs>(
836                                     AllOf(WithMotionAction(HOVER_MOVE), WithButtonState(0),
837                                           WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
838                             VariantWith<NotifyKeyArgs>(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
839                                                              WithKeyCode(expectedKeyCode)))));
840 }
841 
842 INSTANTIATE_TEST_SUITE_P(
843         SideExtraBackAndForward, CursorInputMapperButtonKeyTest,
844         testing::Values(std::make_tuple(BTN_SIDE, AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK),
845                         std::make_tuple(BTN_EXTRA, AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD),
846                         std::make_tuple(BTN_BACK, AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK),
847                         std::make_tuple(BTN_FORWARD, AMOTION_EVENT_BUTTON_FORWARD,
848                                         AKEYCODE_FORWARD)));
849 
TEST_F(CursorInputMapperUnitTest,ProcessWhenModeIsPointerShouldKeepZeroCoords)850 TEST_F(CursorInputMapperUnitTest, ProcessWhenModeIsPointerShouldKeepZeroCoords) {
851     mPropertyMap.addProperty("cursor.mode", "pointer");
852     createMapper();
853 
854     std::list<NotifyArgs> args;
855 
856     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
857     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
858     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
859     EXPECT_THAT(args,
860                 ElementsAre(VariantWith<NotifyMotionArgs>(
861                         AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(HOVER_MOVE),
862                               WithCoords(0.0f, 0.0f), WithPressure(0.0f), WithSize(0.0f),
863                               WithTouchDimensions(0.0f, 0.0f), WithToolDimensions(0.0f, 0.0f),
864                               WithOrientation(0.0f), WithDistance(0.0f)))));
865 }
866 
TEST_F(CursorInputMapperUnitTest,ProcessRegularScroll)867 TEST_F(CursorInputMapperUnitTest, ProcessRegularScroll) {
868     createMapper();
869 
870     std::list<NotifyArgs> args;
871     args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1);
872     args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1);
873     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
874 
875     EXPECT_THAT(args,
876                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
877                             VariantWith<NotifyMotionArgs>(
878                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
879                                           WithScroll(1.0f, 1.0f)))));
880     EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
881 }
882 
TEST_F(CursorInputMapperUnitTest,ProcessHighResScroll)883 TEST_F(CursorInputMapperUnitTest, ProcessHighResScroll) {
884     vd_flags::high_resolution_scroll(true);
885     EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES))
886             .WillRepeatedly(Return(true));
887     EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES))
888             .WillRepeatedly(Return(true));
889     createMapper();
890 
891     std::list<NotifyArgs> args;
892     args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60);
893     args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60);
894     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
895 
896     EXPECT_THAT(args,
897                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
898                             VariantWith<NotifyMotionArgs>(
899                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
900                                           WithScroll(0.5f, 0.5f)))));
901     EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
902 }
903 
TEST_F(CursorInputMapperUnitTest,HighResScrollIgnoresRegularScroll)904 TEST_F(CursorInputMapperUnitTest, HighResScrollIgnoresRegularScroll) {
905     vd_flags::high_resolution_scroll(true);
906     EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES))
907             .WillRepeatedly(Return(true));
908     EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES))
909             .WillRepeatedly(Return(true));
910     createMapper();
911 
912     std::list<NotifyArgs> args;
913     args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60);
914     args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60);
915     args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1);
916     args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1);
917     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
918 
919     EXPECT_THAT(args,
920                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
921                             VariantWith<NotifyMotionArgs>(
922                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
923                                           WithScroll(0.5f, 0.5f)))));
924     EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
925 }
926 
TEST_F(CursorInputMapperUnitTest,ProcessReversedVerticalScroll)927 TEST_F(CursorInputMapperUnitTest, ProcessReversedVerticalScroll) {
928     mReaderConfiguration.mouseReverseVerticalScrollingEnabled = true;
929     createMapper();
930 
931     std::list<NotifyArgs> args;
932     args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1);
933     args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1);
934     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
935 
936     // Reversed vertical scrolling only affects the y-axis, expect it to be -1.0f to indicate the
937     // inverted scroll direction.
938     EXPECT_THAT(args,
939                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
940                             VariantWith<NotifyMotionArgs>(
941                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
942                                           WithScroll(1.0f, -1.0f)))));
943     EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
944 }
945 
TEST_F(CursorInputMapperUnitTest,ProcessHighResReversedVerticalScroll)946 TEST_F(CursorInputMapperUnitTest, ProcessHighResReversedVerticalScroll) {
947     mReaderConfiguration.mouseReverseVerticalScrollingEnabled = true;
948     vd_flags::high_resolution_scroll(true);
949     EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES))
950             .WillRepeatedly(Return(true));
951     EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES))
952             .WillRepeatedly(Return(true));
953     createMapper();
954 
955     std::list<NotifyArgs> args;
956     args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60);
957     args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60);
958     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
959 
960     EXPECT_THAT(args,
961                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
962                             VariantWith<NotifyMotionArgs>(
963                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
964                                           WithScroll(0.5f, -0.5f)))));
965     EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
966 }
967 
968 /**
969  * When Pointer Capture is enabled, we expect to report unprocessed relative movements, so any
970  * pointer acceleration or speed processing should not be applied.
971  */
TEST_F(CursorInputMapperUnitTest,PointerCaptureDisablesVelocityProcessing)972 TEST_F(CursorInputMapperUnitTest, PointerCaptureDisablesVelocityProcessing) {
973     mPropertyMap.addProperty("cursor.mode", "pointer");
974     createMapper();
975 
976     NotifyMotionArgs motionArgs;
977     std::list<NotifyArgs> args;
978 
979     // Move and verify scale is applied.
980     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
981     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
982     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
983     EXPECT_THAT(args,
984                 ElementsAre(VariantWith<NotifyMotionArgs>(
985                         AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(HOVER_MOVE)))));
986     motionArgs = std::get<NotifyMotionArgs>(args.front());
987     const float relX = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
988     const float relY = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
989     ASSERT_GT(relX, 10);
990     ASSERT_GT(relY, 20);
991     args.clear();
992 
993     // Enable Pointer Capture
994     setPointerCapture(true);
995 
996     // Move and verify scale is not applied.
997     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
998     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
999     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1000     EXPECT_THAT(args,
1001                 ElementsAre(VariantWith<NotifyMotionArgs>(
1002                         AllOf(WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
1003                               WithMotionAction(ACTION_MOVE), WithRelativeMotion(10, 20)))));
1004 }
1005 
TEST_F(CursorInputMapperUnitTest,ConfigureDisplayIdNoAssociatedViewport)1006 TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdNoAssociatedViewport) {
1007     // Set up the default display.
1008     mFakePolicy->clearViewports();
1009     mFakePolicy->addDisplayViewport(createPrimaryViewport(ui::Rotation::Rotation0));
1010 
1011     // Set up the secondary display as the display on which the pointer should be shown.
1012     // The InputDevice is not associated with any display.
1013     mFakePolicy->addDisplayViewport(createSecondaryViewport());
1014     mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID);
1015 
1016     createMapper();
1017 
1018     // Ensure input events are generated without display ID or coords, because they will be decided
1019     // later by PointerChoreographer.
1020     std::list<NotifyArgs> args;
1021     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
1022     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
1023     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1024     EXPECT_THAT(args,
1025                 ElementsAre(VariantWith<NotifyMotionArgs>(
1026                         AllOf(WithMotionAction(HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
1027                               WithDisplayId(ui::LogicalDisplayId::INVALID),
1028                               WithCoords(0.0f, 0.0f)))));
1029 }
1030 
TEST_F(CursorInputMapperUnitTest,ConfigureAccelerationWithAssociatedViewport)1031 TEST_F(CursorInputMapperUnitTest, ConfigureAccelerationWithAssociatedViewport) {
1032     mPropertyMap.addProperty("cursor.mode", "pointer");
1033     DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation0);
1034     mReaderConfiguration.setDisplayViewports({primaryViewport});
1035     EXPECT_CALL((*mDevice), getAssociatedViewport).WillRepeatedly(Return(primaryViewport));
1036     mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
1037 
1038     std::list<NotifyArgs> args;
1039 
1040     // Verify that acceleration is being applied by default by checking that the movement is scaled.
1041     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
1042     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
1043     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1044     ASSERT_THAT(args,
1045                 ElementsAre(VariantWith<NotifyMotionArgs>(
1046                         AllOf(WithMotionAction(HOVER_MOVE), WithDisplayId(DISPLAY_ID)))));
1047     const auto& coords = get<NotifyMotionArgs>(args.back()).pointerCoords[0];
1048     ASSERT_GT(coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X), 10.f);
1049     ASSERT_GT(coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y), 20.f);
1050 
1051     // Disable acceleration for the display, and verify that acceleration is no longer applied.
1052     mReaderConfiguration.displaysWithMousePointerAccelerationDisabled.emplace(DISPLAY_ID);
1053     args += mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
1054                                  InputReaderConfiguration::Change::POINTER_SPEED);
1055     args.clear();
1056 
1057     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
1058     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
1059     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1060     ASSERT_THAT(args,
1061                 ElementsAre(VariantWith<NotifyMotionArgs>(AllOf(WithMotionAction(HOVER_MOVE),
1062                                                                 WithDisplayId(DISPLAY_ID),
1063                                                                 WithRelativeMotion(10, 20)))));
1064 }
1065 
TEST_F(CursorInputMapperUnitTest,ConfigureAccelerationOnDisplayChange)1066 TEST_F(CursorInputMapperUnitTest, ConfigureAccelerationOnDisplayChange) {
1067     mPropertyMap.addProperty("cursor.mode", "pointer");
1068     DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation0);
1069     mReaderConfiguration.setDisplayViewports({primaryViewport});
1070     // Disable acceleration for the display.
1071     mReaderConfiguration.displaysWithMousePointerAccelerationDisabled.emplace(DISPLAY_ID);
1072 
1073     // Don't associate the device with the display yet.
1074     EXPECT_CALL((*mDevice), getAssociatedViewport).WillRepeatedly(Return(std::nullopt));
1075     mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
1076 
1077     std::list<NotifyArgs> args;
1078 
1079     // Verify that acceleration is being applied by default by checking that the movement is scaled.
1080     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
1081     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
1082     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1083     ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
1084     const auto& coords = get<NotifyMotionArgs>(args.back()).pointerCoords[0];
1085     ASSERT_GT(coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X), 10.f);
1086     ASSERT_GT(coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y), 20.f);
1087 
1088     // Now associate the device with the display, and verify that acceleration is disabled.
1089     EXPECT_CALL((*mDevice), getAssociatedViewport).WillRepeatedly(Return(primaryViewport));
1090     args += mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
1091                                  InputReaderConfiguration::Change::DISPLAY_INFO);
1092     args.clear();
1093 
1094     args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
1095     args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
1096     args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1097     ASSERT_THAT(args,
1098                 ElementsAre(VariantWith<NotifyMotionArgs>(
1099                         AllOf(WithMotionAction(HOVER_MOVE), WithDisplayId(DISPLAY_ID),
1100                               WithRelativeMotion(10, 20)))));
1101 }
1102 
1103 namespace {
1104 
1105 // Minimum timestamp separation between subsequent input events from a Bluetooth device.
1106 constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
1107 // Maximum smoothing time delta so that we don't generate events too far into the future.
1108 constexpr nsecs_t MAX_BLUETOOTH_SMOOTHING_DELTA = ms2ns(32);
1109 
1110 } // namespace
1111 
1112 // --- BluetoothCursorInputMapperUnitTest ---
1113 
1114 class BluetoothCursorInputMapperUnitTest : public CursorInputMapperUnitTestBase {
1115 protected:
SetUp()1116     void SetUp() override { SetUpWithBus(BUS_BLUETOOTH); }
1117 };
1118 
TEST_F(BluetoothCursorInputMapperUnitTest,TimestampSmoothening)1119 TEST_F(BluetoothCursorInputMapperUnitTest, TimestampSmoothening) {
1120     mPropertyMap.addProperty("cursor.mode", "pointer");
1121     createMapper();
1122     std::list<NotifyArgs> argsList;
1123 
1124     nsecs_t kernelEventTime = ARBITRARY_TIME;
1125     nsecs_t expectedEventTime = ARBITRARY_TIME;
1126     argsList += process(kernelEventTime, EV_REL, REL_X, 1);
1127     argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
1128     EXPECT_THAT(argsList,
1129                 ElementsAre(VariantWith<NotifyMotionArgs>(
1130                         AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(expectedEventTime)))));
1131     argsList.clear();
1132 
1133     // Process several events that come in quick succession, according to their timestamps.
1134     for (int i = 0; i < 3; i++) {
1135         constexpr static nsecs_t delta = ms2ns(1);
1136         static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
1137         kernelEventTime += delta;
1138         expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
1139 
1140         argsList += process(kernelEventTime, EV_REL, REL_X, 1);
1141         argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
1142         EXPECT_THAT(argsList,
1143                     ElementsAre(VariantWith<NotifyMotionArgs>(
1144                             AllOf(WithMotionAction(HOVER_MOVE),
1145                                   WithEventTime(expectedEventTime)))));
1146         argsList.clear();
1147     }
1148 }
1149 
TEST_F(BluetoothCursorInputMapperUnitTest,TimestampSmootheningIsCapped)1150 TEST_F(BluetoothCursorInputMapperUnitTest, TimestampSmootheningIsCapped) {
1151     mPropertyMap.addProperty("cursor.mode", "pointer");
1152     createMapper();
1153     std::list<NotifyArgs> argsList;
1154 
1155     nsecs_t expectedEventTime = ARBITRARY_TIME;
1156     argsList += process(ARBITRARY_TIME, EV_REL, REL_X, 1);
1157     argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1158     EXPECT_THAT(argsList,
1159                 ElementsAre(VariantWith<NotifyMotionArgs>(
1160                         AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(expectedEventTime)))));
1161     argsList.clear();
1162 
1163     // Process several events with the same timestamp from the kernel.
1164     // Ensure that we do not generate events too far into the future.
1165     constexpr static int32_t numEvents =
1166             MAX_BLUETOOTH_SMOOTHING_DELTA / MIN_BLUETOOTH_TIMESTAMP_DELTA;
1167     for (int i = 0; i < numEvents; i++) {
1168         expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
1169 
1170         argsList += process(ARBITRARY_TIME, EV_REL, REL_X, 1);
1171         argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1172         EXPECT_THAT(argsList,
1173                     ElementsAre(VariantWith<NotifyMotionArgs>(
1174                             AllOf(WithMotionAction(HOVER_MOVE),
1175                                   WithEventTime(expectedEventTime)))));
1176         argsList.clear();
1177     }
1178 
1179     // By processing more events with the same timestamp, we should not generate events with a
1180     // timestamp that is more than the specified max time delta from the timestamp at its injection.
1181     const nsecs_t cappedEventTime = ARBITRARY_TIME + MAX_BLUETOOTH_SMOOTHING_DELTA;
1182     for (int i = 0; i < 3; i++) {
1183         argsList += process(ARBITRARY_TIME, EV_REL, REL_X, 1);
1184         argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1185         EXPECT_THAT(argsList,
1186                     ElementsAre(VariantWith<NotifyMotionArgs>(
1187                             AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(cappedEventTime)))));
1188         argsList.clear();
1189     }
1190 }
1191 
TEST_F(BluetoothCursorInputMapperUnitTest,TimestampSmootheningNotUsed)1192 TEST_F(BluetoothCursorInputMapperUnitTest, TimestampSmootheningNotUsed) {
1193     mPropertyMap.addProperty("cursor.mode", "pointer");
1194     createMapper();
1195     std::list<NotifyArgs> argsList;
1196 
1197     nsecs_t kernelEventTime = ARBITRARY_TIME;
1198     nsecs_t expectedEventTime = ARBITRARY_TIME;
1199     argsList += process(kernelEventTime, EV_REL, REL_X, 1);
1200     argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
1201     EXPECT_THAT(argsList,
1202                 ElementsAre(VariantWith<NotifyMotionArgs>(
1203                         AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(expectedEventTime)))));
1204     argsList.clear();
1205 
1206     // If the next event has a timestamp that is sufficiently spaced out so that Bluetooth timestamp
1207     // smoothening is not needed, its timestamp is not affected.
1208     kernelEventTime += MAX_BLUETOOTH_SMOOTHING_DELTA + ms2ns(1);
1209     expectedEventTime = kernelEventTime;
1210 
1211     argsList += process(kernelEventTime, EV_REL, REL_X, 1);
1212     argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
1213     EXPECT_THAT(argsList,
1214                 ElementsAre(VariantWith<NotifyMotionArgs>(
1215                         AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(expectedEventTime)))));
1216     argsList.clear();
1217 }
1218 
1219 } // namespace android
1220