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 <CapturedTouchpadEventConverter.h>
18 
19 #include <list>
20 #include <memory>
21 
22 #include <EventHub.h>
23 #include <com_android_input_flags.h>
24 #include <gtest/gtest.h>
25 #include <linux/input-event-codes.h>
26 #include <linux/input.h>
27 #include <utils/StrongPointer.h>
28 
29 #include "FakeEventHub.h"
30 #include "FakeInputReaderPolicy.h"
31 #include "InstrumentedInputReader.h"
32 #include "TestConstants.h"
33 #include "TestEventMatchers.h"
34 #include "TestInputListener.h"
35 
36 namespace input_flags = com::android::input::flags;
37 
38 namespace android {
39 
40 using testing::AllOf;
41 using testing::Each;
42 using testing::ElementsAre;
43 using testing::VariantWith;
44 
45 class CapturedTouchpadEventConverterTest : public testing::Test {
46 public:
CapturedTouchpadEventConverterTest()47     CapturedTouchpadEventConverterTest()
48           : mFakeEventHub(std::make_unique<FakeEventHub>()),
49             mFakePolicy(sp<FakeInputReaderPolicy>::make()),
50             mReader(mFakeEventHub, mFakePolicy, mFakeListener),
51             mDevice(newDevice()),
52             mDeviceContext(*mDevice, EVENTHUB_ID) {
53         input_flags::include_relative_axis_values_for_captured_touchpads(true);
54 
55         const size_t slotCount = 8;
56         mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, 0, slotCount - 1, 0, 0, 0);
57         mAccumulator.configure(mDeviceContext, slotCount, /*usingSlotsProtocol=*/true);
58     }
59 
60 protected:
61     static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
62     static constexpr int32_t EVENTHUB_ID = 1;
63 
newDevice()64     std::shared_ptr<InputDevice> newDevice() {
65         InputDeviceIdentifier identifier;
66         identifier.name = "device";
67         identifier.location = "USB1";
68         identifier.bus = 0;
69         std::shared_ptr<InputDevice> device =
70                 std::make_shared<InputDevice>(mReader.getContext(), DEVICE_ID, /*generation=*/2,
71                                               identifier);
72         mReader.pushNextDevice(device);
73         mFakeEventHub->addDevice(EVENTHUB_ID, identifier.name, InputDeviceClass::TOUCHPAD,
74                                  identifier.bus);
75         mReader.loopOnce();
76         return device;
77     }
78 
addBasicAxesToEventHub()79     void addBasicAxesToEventHub() {
80         mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
81         mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
82         mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, 0, 256, 0, 0, 0);
83         mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 1000, 0, 0, 0);
84         mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 1000, 0, 0, 0);
85     }
86 
createConverter()87     CapturedTouchpadEventConverter createConverter() {
88         addBasicAxesToEventHub();
89         return CapturedTouchpadEventConverter(*mReader.getContext(), mDeviceContext, mAccumulator,
90                                               DEVICE_ID);
91     }
92 
processAxis(CapturedTouchpadEventConverter & conv,int32_t type,int32_t code,int32_t value)93     void processAxis(CapturedTouchpadEventConverter& conv, int32_t type, int32_t code,
94                      int32_t value) {
95         RawEvent event;
96         event.when = ARBITRARY_TIME;
97         event.readTime = READ_TIME;
98         event.deviceId = EVENTHUB_ID;
99         event.type = type;
100         event.code = code;
101         event.value = value;
102         std::list<NotifyArgs> out = conv.process(event);
103         EXPECT_TRUE(out.empty());
104     }
105 
processSync(CapturedTouchpadEventConverter & conv)106     std::list<NotifyArgs> processSync(CapturedTouchpadEventConverter& conv) {
107         RawEvent event;
108         event.when = ARBITRARY_TIME;
109         event.readTime = READ_TIME;
110         event.deviceId = EVENTHUB_ID;
111         event.type = EV_SYN;
112         event.code = SYN_REPORT;
113         event.value = 0;
114         return conv.process(event);
115     }
116 
processSyncAndExpectSingleMotionArg(CapturedTouchpadEventConverter & conv)117     NotifyMotionArgs processSyncAndExpectSingleMotionArg(CapturedTouchpadEventConverter& conv) {
118         std::list<NotifyArgs> args = processSync(conv);
119         EXPECT_EQ(1u, args.size());
120         return std::get<NotifyMotionArgs>(args.front());
121     }
122 
123     std::shared_ptr<FakeEventHub> mFakeEventHub;
124     sp<FakeInputReaderPolicy> mFakePolicy;
125     TestInputListener mFakeListener;
126     InstrumentedInputReader mReader;
127     std::shared_ptr<InputDevice> mDevice;
128     InputDeviceContext mDeviceContext;
129     MultiTouchMotionAccumulator mAccumulator;
130 };
131 
TEST_F(CapturedTouchpadEventConverterTest,MotionRanges_allAxesPresent_populatedCorrectly)132 TEST_F(CapturedTouchpadEventConverterTest, MotionRanges_allAxesPresent_populatedCorrectly) {
133     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
134     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, -500, 2000, 0, 0, 40);
135     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 1100, 0, 0, 35);
136     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 1000, 0, 0, 30);
137     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 900, 0, 0, 25);
138     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 800, 0, 0, 20);
139     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, -3, 4, 0, 0, 0);
140     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, 0, 256, 0, 0, 0);
141     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
142                                         DEVICE_ID);
143 
144     InputDeviceInfo info;
145     conv.populateMotionRanges(info);
146 
147     // Most axes should have min, max, and resolution matching the evdev axes.
148     const InputDeviceInfo::MotionRange* posX =
149             info.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHPAD);
150     ASSERT_NE(nullptr, posX);
151     EXPECT_NEAR(0, posX->min, EPSILON);
152     EXPECT_NEAR(4000, posX->max, EPSILON);
153     EXPECT_NEAR(45, posX->resolution, EPSILON);
154 
155     const InputDeviceInfo::MotionRange* posY =
156             info.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHPAD);
157     ASSERT_NE(nullptr, posY);
158     EXPECT_NEAR(-500, posY->min, EPSILON);
159     EXPECT_NEAR(2000, posY->max, EPSILON);
160     EXPECT_NEAR(40, posY->resolution, EPSILON);
161 
162     const InputDeviceInfo::MotionRange* touchMajor =
163             info.getMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR, AINPUT_SOURCE_TOUCHPAD);
164     ASSERT_NE(nullptr, touchMajor);
165     EXPECT_NEAR(0, touchMajor->min, EPSILON);
166     EXPECT_NEAR(1100, touchMajor->max, EPSILON);
167     EXPECT_NEAR(35, touchMajor->resolution, EPSILON);
168 
169     const InputDeviceInfo::MotionRange* touchMinor =
170             info.getMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR, AINPUT_SOURCE_TOUCHPAD);
171     ASSERT_NE(nullptr, touchMinor);
172     EXPECT_NEAR(0, touchMinor->min, EPSILON);
173     EXPECT_NEAR(1000, touchMinor->max, EPSILON);
174     EXPECT_NEAR(30, touchMinor->resolution, EPSILON);
175 
176     const InputDeviceInfo::MotionRange* toolMajor =
177             info.getMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR, AINPUT_SOURCE_TOUCHPAD);
178     ASSERT_NE(nullptr, toolMajor);
179     EXPECT_NEAR(0, toolMajor->min, EPSILON);
180     EXPECT_NEAR(900, toolMajor->max, EPSILON);
181     EXPECT_NEAR(25, toolMajor->resolution, EPSILON);
182 
183     const InputDeviceInfo::MotionRange* toolMinor =
184             info.getMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR, AINPUT_SOURCE_TOUCHPAD);
185     ASSERT_NE(nullptr, toolMinor);
186     EXPECT_NEAR(0, toolMinor->min, EPSILON);
187     EXPECT_NEAR(800, toolMinor->max, EPSILON);
188     EXPECT_NEAR(20, toolMinor->resolution, EPSILON);
189 
190     // ...except for the relative motion axes, derived from the corresponding absolute ones:
191     const InputDeviceInfo::MotionRange* relX =
192             info.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, AINPUT_SOURCE_TOUCHPAD);
193     ASSERT_NE(nullptr, relX);
194     EXPECT_NEAR(-4000, relX->min, EPSILON);
195     EXPECT_NEAR(4000, relX->max, EPSILON);
196     EXPECT_NEAR(45, relX->resolution, EPSILON);
197 
198     const InputDeviceInfo::MotionRange* relY =
199             info.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, AINPUT_SOURCE_TOUCHPAD);
200     ASSERT_NE(nullptr, relY);
201     EXPECT_NEAR(-2500, relY->min, EPSILON);
202     EXPECT_NEAR(2500, relY->max, EPSILON);
203     EXPECT_NEAR(40, relY->resolution, EPSILON);
204 
205     // ...orientation and pressure, which get scaled:
206     const InputDeviceInfo::MotionRange* orientation =
207             info.getMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, AINPUT_SOURCE_TOUCHPAD);
208     ASSERT_NE(nullptr, orientation);
209     EXPECT_NEAR(-M_PI_2, orientation->min, EPSILON);
210     EXPECT_NEAR(M_PI_2, orientation->max, EPSILON);
211     EXPECT_NEAR(0, orientation->resolution, EPSILON);
212 
213     const InputDeviceInfo::MotionRange* pressure =
214             info.getMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_TOUCHPAD);
215     ASSERT_NE(nullptr, pressure);
216     EXPECT_NEAR(0, pressure->min, EPSILON);
217     EXPECT_NEAR(1, pressure->max, EPSILON);
218     EXPECT_NEAR(0, pressure->resolution, EPSILON);
219 
220     // ... and size, which is generated from other values.
221     const InputDeviceInfo::MotionRange* size =
222             info.getMotionRange(AMOTION_EVENT_AXIS_SIZE, AINPUT_SOURCE_TOUCHPAD);
223     ASSERT_NE(nullptr, size);
224     EXPECT_NEAR(0, size->min, EPSILON);
225     EXPECT_NEAR(1, size->max, EPSILON);
226     EXPECT_NEAR(0, size->resolution, EPSILON);
227 }
228 
TEST_F(CapturedTouchpadEventConverterTest,MotionRanges_bareMinimumAxesPresent_populatedCorrectly)229 TEST_F(CapturedTouchpadEventConverterTest, MotionRanges_bareMinimumAxesPresent_populatedCorrectly) {
230     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
231     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
232     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
233                                         DEVICE_ID);
234 
235     InputDeviceInfo info;
236     conv.populateMotionRanges(info);
237 
238     // Only the bare minimum motion ranges should be reported, and no others (e.g. size shouldn't be
239     // present, since it's generated from axes that aren't provided by this device).
240     EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHPAD));
241     EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHPAD));
242     EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, AINPUT_SOURCE_TOUCHPAD));
243     EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, AINPUT_SOURCE_TOUCHPAD));
244     EXPECT_EQ(4u, info.getMotionRanges().size());
245 }
246 
TEST_F(CapturedTouchpadEventConverterTest,OneFinger_motionReportedCorrectly)247 TEST_F(CapturedTouchpadEventConverterTest, OneFinger_motionReportedCorrectly) {
248     CapturedTouchpadEventConverter conv = createConverter();
249 
250     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
251     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
252     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
253     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
254 
255     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
256     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
257 
258     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
259                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
260                       WithCoords(50, 100), WithRelativeMotion(0, 0),
261                       WithToolType(ToolType::FINGER)));
262 
263     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
264     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 99);
265 
266     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
267                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
268                       WithCoords(52, 99), WithRelativeMotion(2, -1),
269                       WithToolType(ToolType::FINGER)));
270 
271     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
272     processAxis(conv, EV_KEY, BTN_TOUCH, 0);
273     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
274 
275     std::list<NotifyArgs> args = processSync(conv);
276     EXPECT_THAT(args,
277                 ElementsAre(VariantWith<NotifyMotionArgs>(
278                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
279                             VariantWith<NotifyMotionArgs>(
280                                     WithMotionAction(AMOTION_EVENT_ACTION_UP))));
281     EXPECT_THAT(args,
282                 Each(VariantWith<NotifyMotionArgs>(
283                         AllOf(WithCoords(52, 99), WithRelativeMotion(0, 0), WithPointerCount(1u),
284                               WithToolType(ToolType::FINGER)))));
285 }
286 
TEST_F(CapturedTouchpadEventConverterTest,OneFinger_touchDimensionsPassedThrough)287 TEST_F(CapturedTouchpadEventConverterTest, OneFinger_touchDimensionsPassedThrough) {
288     addBasicAxesToEventHub();
289     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 1000, 0, 0, 0);
290     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 1000, 0, 0, 0);
291     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
292                                         DEVICE_ID);
293 
294     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
295     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
296     processAxis(conv, EV_ABS, ABS_MT_TOUCH_MAJOR, 250);
297     processAxis(conv, EV_ABS, ABS_MT_TOUCH_MINOR, 120);
298     processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 400);
299     processAxis(conv, EV_ABS, ABS_MT_WIDTH_MINOR, 200);
300 
301     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
302     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
303 
304     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
305                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
306                       WithTouchDimensions(250, 120), WithToolDimensions(400, 200)));
307 }
308 
TEST_F(CapturedTouchpadEventConverterTest,OneFinger_orientationCalculatedCorrectly)309 TEST_F(CapturedTouchpadEventConverterTest, OneFinger_orientationCalculatedCorrectly) {
310     addBasicAxesToEventHub();
311     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, -3, 4, 0, 0, 0);
312     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
313                                         DEVICE_ID);
314 
315     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
316     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
317     processAxis(conv, EV_ABS, ABS_MT_ORIENTATION, -3);
318     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
319     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
320 
321     EXPECT_NEAR(-3 * M_PI / 8,
322                 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
323                         AMOTION_EVENT_AXIS_ORIENTATION),
324                 EPSILON);
325 
326     processAxis(conv, EV_ABS, ABS_MT_ORIENTATION, 0);
327 
328     EXPECT_NEAR(0,
329                 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
330                         AMOTION_EVENT_AXIS_ORIENTATION),
331                 EPSILON);
332 
333     processAxis(conv, EV_ABS, ABS_MT_ORIENTATION, 4);
334 
335     EXPECT_NEAR(M_PI / 2,
336                 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
337                         AMOTION_EVENT_AXIS_ORIENTATION),
338                 EPSILON);
339 }
340 
TEST_F(CapturedTouchpadEventConverterTest,OneFinger_pressureScaledCorrectly)341 TEST_F(CapturedTouchpadEventConverterTest, OneFinger_pressureScaledCorrectly) {
342     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
343     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
344     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, 0, 256, 0, 0, 0);
345     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
346                                         DEVICE_ID);
347 
348     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
349     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
350     processAxis(conv, EV_ABS, ABS_MT_PRESSURE, 128);
351     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
352     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
353 
354     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv), WithPressure(0.5));
355 }
356 
TEST_F(CapturedTouchpadEventConverterTest,OneFinger_withAllSizeAxes_sizeCalculatedFromTouchMajorMinorAverage)357 TEST_F(CapturedTouchpadEventConverterTest,
358        OneFinger_withAllSizeAxes_sizeCalculatedFromTouchMajorMinorAverage) {
359     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
360     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
361     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 256, 0, 0, 0);
362     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 256, 0, 0, 0);
363     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
364     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 256, 0, 0, 0);
365     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
366                                         DEVICE_ID);
367 
368     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
369     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
370     processAxis(conv, EV_ABS, ABS_MT_TOUCH_MAJOR, 138);
371     processAxis(conv, EV_ABS, ABS_MT_TOUCH_MINOR, 118);
372     processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 200);
373     processAxis(conv, EV_ABS, ABS_MT_WIDTH_MINOR, 210);
374     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
375     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
376 
377     EXPECT_NEAR(0.5,
378                 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
379                         AMOTION_EVENT_AXIS_SIZE),
380                 EPSILON);
381 }
382 
TEST_F(CapturedTouchpadEventConverterTest,OneFinger_withMajorDimensionsOnly_sizeCalculatedFromTouchMajor)383 TEST_F(CapturedTouchpadEventConverterTest,
384        OneFinger_withMajorDimensionsOnly_sizeCalculatedFromTouchMajor) {
385     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
386     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
387     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 256, 0, 0, 0);
388     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
389     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
390                                         DEVICE_ID);
391 
392     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
393     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
394     processAxis(conv, EV_ABS, ABS_MT_TOUCH_MAJOR, 128);
395     processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 200);
396     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
397     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
398 
399     EXPECT_NEAR(0.5,
400                 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
401                         AMOTION_EVENT_AXIS_SIZE),
402                 EPSILON);
403 }
404 
TEST_F(CapturedTouchpadEventConverterTest,OneFinger_withToolDimensionsOnly_sizeCalculatedFromToolMajorMinorAverage)405 TEST_F(CapturedTouchpadEventConverterTest,
406        OneFinger_withToolDimensionsOnly_sizeCalculatedFromToolMajorMinorAverage) {
407     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
408     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
409     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
410     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 256, 0, 0, 0);
411     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
412                                         DEVICE_ID);
413 
414     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
415     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
416     processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 138);
417     processAxis(conv, EV_ABS, ABS_MT_WIDTH_MINOR, 118);
418     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
419     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
420 
421     EXPECT_NEAR(0.5,
422                 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
423                         AMOTION_EVENT_AXIS_SIZE),
424                 EPSILON);
425 }
426 
TEST_F(CapturedTouchpadEventConverterTest,OneFinger_withToolMajorOnly_sizeCalculatedFromTouchMajor)427 TEST_F(CapturedTouchpadEventConverterTest,
428        OneFinger_withToolMajorOnly_sizeCalculatedFromTouchMajor) {
429     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
430     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
431     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
432     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
433                                         DEVICE_ID);
434 
435     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
436     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
437     processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 128);
438     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
439     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
440 
441     EXPECT_NEAR(0.5,
442                 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
443                         AMOTION_EVENT_AXIS_SIZE),
444                 EPSILON);
445 }
446 
TEST_F(CapturedTouchpadEventConverterTest,OnePalm_neverReported)447 TEST_F(CapturedTouchpadEventConverterTest, OnePalm_neverReported) {
448     addBasicAxesToEventHub();
449     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
450     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
451                                         DEVICE_ID);
452 
453     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
454     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
455     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
456     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
457     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
458     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
459     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
460 
461     EXPECT_EQ(0u, processSync(conv).size());
462 
463     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
464 
465     EXPECT_EQ(0u, processSync(conv).size());
466 
467     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
468     processAxis(conv, EV_KEY, BTN_TOUCH, 0);
469     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
470 
471     EXPECT_EQ(0u, processSync(conv).size());
472 }
473 
TEST_F(CapturedTouchpadEventConverterTest,FingerTurningIntoPalm_cancelled)474 TEST_F(CapturedTouchpadEventConverterTest, FingerTurningIntoPalm_cancelled) {
475     addBasicAxesToEventHub();
476     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
477     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
478                                         DEVICE_ID);
479 
480     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
481     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
482     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
483     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
484     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
485     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
486     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
487 
488     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
489                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::FINGER),
490                       WithPointerCount(1u)));
491 
492     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
493     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
494 
495     std::list<NotifyArgs> args = processSync(conv);
496     ASSERT_EQ(2u, args.size());
497     EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
498                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u)));
499     args.pop_front();
500     EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
501                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL), WithPointerCount(1u)));
502 
503     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
504 
505     EXPECT_EQ(0u, processSync(conv).size());
506 
507     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
508     processAxis(conv, EV_KEY, BTN_TOUCH, 0);
509     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
510 
511     EXPECT_EQ(0u, processSync(conv).size());
512 }
513 
TEST_F(CapturedTouchpadEventConverterTest,PalmTurningIntoFinger_reported)514 TEST_F(CapturedTouchpadEventConverterTest, PalmTurningIntoFinger_reported) {
515     addBasicAxesToEventHub();
516     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
517     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
518                                         DEVICE_ID);
519 
520     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
521     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
522     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
523     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
524     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
525     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
526     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
527 
528     EXPECT_EQ(0u, processSync(conv).size());
529 
530     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
531     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
532 
533     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
534                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
535                       WithCoords(51, 100), WithRelativeMotion(0, 0)));
536 
537     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
538 
539     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
540                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
541                       WithCoords(52, 100), WithRelativeMotion(1, 0)));
542 }
543 
TEST_F(CapturedTouchpadEventConverterTest,FingerArrivingAfterPalm_onlyFingerReported)544 TEST_F(CapturedTouchpadEventConverterTest, FingerArrivingAfterPalm_onlyFingerReported) {
545     addBasicAxesToEventHub();
546     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
547     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
548                                         DEVICE_ID);
549 
550     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
551     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
552     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
553     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
554     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
555     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
556     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
557 
558     EXPECT_EQ(0u, processSync(conv).size());
559 
560     processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
561     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
562     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 100);
563     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 150);
564     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
565     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
566     processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
567 
568     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
569                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
570                       WithCoords(100, 150)));
571 
572     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
573     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
574     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 102);
575     processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
576     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 98);
577     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 148);
578 
579     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
580                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
581                       WithCoords(98, 148), WithRelativeMotion(-2, -2)));
582 }
583 
TEST_F(CapturedTouchpadEventConverterTest,FingerAndFingerTurningIntoPalm_partiallyCancelled)584 TEST_F(CapturedTouchpadEventConverterTest, FingerAndFingerTurningIntoPalm_partiallyCancelled) {
585     addBasicAxesToEventHub();
586     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
587     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
588                                         DEVICE_ID);
589 
590     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
591     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
592     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
593     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
594 
595     processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
596     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
597     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 250);
598     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
599 
600     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
601     processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
602 
603     EXPECT_THAT(processSync(conv),
604                 ElementsAre(VariantWith<NotifyMotionArgs>(
605                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
606                                           WithPointerCount(1u), WithToolType(ToolType::FINGER))),
607                             VariantWith<NotifyMotionArgs>(
608                                     AllOf(WithMotionAction(
609                                                   AMOTION_EVENT_ACTION_POINTER_DOWN |
610                                                   1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
611                                           WithPointerCount(2u),
612                                           WithPointerToolType(0, ToolType::FINGER),
613                                           WithPointerToolType(1, ToolType::FINGER)))));
614 
615     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
616     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
617 
618     processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
619     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 251);
620     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
621 
622     std::list<NotifyArgs> args = processSync(conv);
623     EXPECT_THAT(args,
624                 ElementsAre(VariantWith<NotifyMotionArgs>(
625                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
626                             VariantWith<NotifyMotionArgs>(
627                                     AllOf(WithMotionAction(
628                                                   AMOTION_EVENT_ACTION_POINTER_UP |
629                                                   1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
630                                           WithFlags(AMOTION_EVENT_FLAG_CANCELED)))));
631     EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithPointerCount(2u))));
632 }
633 
TEST_F(CapturedTouchpadEventConverterTest,FingerAndPalmTurningIntoFinger_reported)634 TEST_F(CapturedTouchpadEventConverterTest, FingerAndPalmTurningIntoFinger_reported) {
635     addBasicAxesToEventHub();
636     mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
637     CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
638                                         DEVICE_ID);
639 
640     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
641     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
642     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
643     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
644 
645     processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
646     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
647     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 250);
648     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
649 
650     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
651     processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
652 
653     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
654                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
655                       WithToolType(ToolType::FINGER)));
656 
657     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
658     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
659 
660     processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
661     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 251);
662     processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
663 
664     EXPECT_THAT(processSync(conv),
665                 ElementsAre(VariantWith<NotifyMotionArgs>(
666                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
667                                           WithPointerCount(1u))),
668                             VariantWith<NotifyMotionArgs>(
669                                     AllOf(WithMotionAction(
670                                                   AMOTION_EVENT_ACTION_POINTER_DOWN |
671                                                   1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
672                                           WithPointerCount(2u)))));
673 }
674 
TEST_F(CapturedTouchpadEventConverterTest,TwoFingers_motionReportedCorrectly)675 TEST_F(CapturedTouchpadEventConverterTest, TwoFingers_motionReportedCorrectly) {
676     CapturedTouchpadEventConverter conv = createConverter();
677 
678     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
679     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
680     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
681     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
682 
683     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
684     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
685 
686     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
687                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
688                       WithCoords(50, 100), WithRelativeMotion(0, 0),
689                       WithToolType(ToolType::FINGER)));
690 
691     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
692     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
693     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 99);
694 
695     processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
696     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
697     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 250);
698     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 200);
699 
700     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
701     processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
702 
703     EXPECT_THAT(processSync(conv),
704                 ElementsAre(VariantWith<NotifyMotionArgs>(
705                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
706                                           WithPointerCount(1u), WithCoords(52, 99),
707                                           WithRelativeMotion(2, -1),
708                                           WithToolType(ToolType::FINGER))),
709                             VariantWith<NotifyMotionArgs>(
710                                     AllOf(WithMotionAction(
711                                                   AMOTION_EVENT_ACTION_POINTER_DOWN |
712                                                   1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
713                                           WithPointerCount(2u), WithPointerCoords(0, 52, 99),
714                                           WithPointerRelativeMotion(0, 0, 0),
715                                           WithPointerCoords(1, 250, 200),
716                                           WithPointerRelativeMotion(1, 0, 0),
717                                           WithPointerToolType(0, ToolType::FINGER),
718                                           WithPointerToolType(1, ToolType::FINGER)))));
719 
720     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
721     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
722     processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
723     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 255);
724     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 202);
725 
726     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
727     processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
728 
729     std::list<NotifyArgs> args = processSync(conv);
730     EXPECT_THAT(args,
731                 ElementsAre(VariantWith<NotifyMotionArgs>(
732                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
733                                           WithPointerRelativeMotion(1, 5, 2))),
734                             VariantWith<NotifyMotionArgs>(
735                                     AllOf(WithMotionAction(
736                                                   AMOTION_EVENT_ACTION_POINTER_UP |
737                                                   0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
738                                           WithPointerRelativeMotion(1, 0, 0)))));
739     EXPECT_THAT(args,
740                 Each(VariantWith<NotifyMotionArgs>(
741                         AllOf(WithPointerCount(2u), WithPointerCoords(0, 52, 99),
742                               WithPointerRelativeMotion(0, 0, 0), WithPointerCoords(1, 255, 202),
743                               WithPointerToolType(1, ToolType::FINGER),
744                               WithPointerToolType(0, ToolType::FINGER)))));
745 
746     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
747     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
748     processAxis(conv, EV_KEY, BTN_TOUCH, 0);
749 
750     args = processSync(conv);
751     EXPECT_THAT(args,
752                 ElementsAre(VariantWith<NotifyMotionArgs>(
753                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
754                             VariantWith<NotifyMotionArgs>(
755                                     WithMotionAction(AMOTION_EVENT_ACTION_UP))));
756     EXPECT_THAT(args,
757                 Each(VariantWith<NotifyMotionArgs>(AllOf(WithPointerCount(1u), WithCoords(255, 202),
758                                                          WithRelativeMotion(0, 0),
759                                                          WithToolType(ToolType::FINGER)))));
760 }
761 
TEST_F(CapturedTouchpadEventConverterTest,RelativeMotionAxesClearedForNewFingerInSlot)762 TEST_F(CapturedTouchpadEventConverterTest, RelativeMotionAxesClearedForNewFingerInSlot) {
763     CapturedTouchpadEventConverter conv = createConverter();
764     // Put down one finger.
765     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
766     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
767     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
768     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
769 
770     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
771     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
772 
773     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
774                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
775                       WithCoords(50, 100), WithRelativeMotion(0, 0)));
776 
777     // Move it in negative X and Y directions.
778     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 47);
779     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 97);
780 
781     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
782                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithCoords(47, 97),
783                       WithRelativeMotion(-3, -3)));
784 
785     // Lift it.
786     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
787     processAxis(conv, EV_KEY, BTN_TOUCH, 0);
788     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
789 
790     std::list<NotifyArgs> args = processSync(conv);
791     EXPECT_THAT(args,
792                 ElementsAre(VariantWith<NotifyMotionArgs>(
793                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
794                             VariantWith<NotifyMotionArgs>(
795                                     WithMotionAction(AMOTION_EVENT_ACTION_UP))));
796     EXPECT_THAT(args,
797                 Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(47, 97),
798                                                          WithRelativeMotion(0, 0),
799                                                          WithPointerCount(1u)))));
800 
801     // Put down another finger using the same slot. Relative axis values should be cleared.
802     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
803     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 60);
804     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 60);
805 
806     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
807     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
808 
809     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
810                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
811                       WithCoords(60, 60), WithRelativeMotion(0, 0)));
812 
813     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 64);
814     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 58);
815 
816     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
817                 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
818                       WithCoords(64, 58), WithRelativeMotion(4, -2)));
819 }
820 
821 // Pointer IDs max out at 31, and so must be reused once a touch is lifted to avoid running out.
TEST_F(CapturedTouchpadEventConverterTest,PointerIdsReusedAfterLift)822 TEST_F(CapturedTouchpadEventConverterTest, PointerIdsReusedAfterLift) {
823     CapturedTouchpadEventConverter conv = createConverter();
824 
825     // Put down two fingers, which should get IDs 0 and 1.
826     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
827     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
828     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 10);
829     processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
830     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
831     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 20);
832 
833     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
834     processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
835 
836     EXPECT_THAT(processSync(conv),
837                 ElementsAre(VariantWith<NotifyMotionArgs>(
838                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
839                                           WithPointerCount(1u),
840                                           WithPointerId(/*index=*/0, /*id=*/0))),
841                             VariantWith<NotifyMotionArgs>(
842                                     AllOf(WithMotionAction(
843                                                   AMOTION_EVENT_ACTION_POINTER_DOWN |
844                                                   1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
845                                           WithPointerCount(2u),
846                                           WithPointerId(/*index=*/0, /*id=*/0),
847                                           WithPointerId(/*index=*/1, /*id=*/1)))));
848 
849     // Lift the finger in slot 0, freeing up pointer ID 0...
850     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
851     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
852 
853     // ...and simultaneously add a finger in slot 2.
854     processAxis(conv, EV_ABS, ABS_MT_SLOT, 2);
855     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 3);
856     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 30);
857 
858     std::list<NotifyArgs> args = processSync(conv);
859     // Slot 1 being present will result in a MOVE event, even though it hasn't actually moved (see
860     // comments in CapturedTouchpadEventConverter::sync).
861     EXPECT_THAT(args,
862                 ElementsAre(VariantWith<NotifyMotionArgs>(
863                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
864                                           WithPointerId(/*index=*/0, /*id=*/0),
865                                           WithPointerId(/*index=*/1, /*id=*/1))),
866                             VariantWith<NotifyMotionArgs>(
867                                     AllOf(WithMotionAction(
868                                                   AMOTION_EVENT_ACTION_POINTER_UP |
869                                                   0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
870                                           WithPointerId(/*index=*/0, /*id=*/0),
871                                           WithPointerId(/*index=*/1, /*id=*/1))),
872                             // Slot 0 being lifted causes the finger from slot 1 to move up to index
873                             // 0, but keep its previous ID. The new finger in slot 2 should take ID
874                             // 0, which was just freed up.
875                             VariantWith<NotifyMotionArgs>(
876                                     AllOf(WithMotionAction(
877                                                   AMOTION_EVENT_ACTION_POINTER_DOWN |
878                                                   1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
879                                           WithPointerId(/*index=*/0, /*id=*/1),
880                                           WithPointerId(/*index=*/1, /*id=*/0)))));
881     EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithPointerCount(2u))));
882 }
883 
884 // Motion events without any pointers are invalid, so when a button press is reported in the same
885 // frame as a touch down, the button press must be reported second. Similarly with a button release
886 // and a touch lift.
TEST_F(CapturedTouchpadEventConverterTest,ButtonPressedAndReleasedInSameFrameAsTouch_ReportedWithPointers)887 TEST_F(CapturedTouchpadEventConverterTest,
888        ButtonPressedAndReleasedInSameFrameAsTouch_ReportedWithPointers) {
889     CapturedTouchpadEventConverter conv = createConverter();
890 
891     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
892     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
893     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
894     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
895     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
896     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
897 
898     processAxis(conv, EV_KEY, BTN_LEFT, 1);
899 
900     EXPECT_THAT(processSync(conv),
901                 ElementsAre(VariantWith<NotifyMotionArgs>(
902                                     WithMotionAction(AMOTION_EVENT_ACTION_DOWN)),
903                             VariantWith<NotifyMotionArgs>(
904                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
905                                           WithPointerCount(1u), WithCoords(50, 100),
906                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
907                                           WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)))));
908 
909     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
910     processAxis(conv, EV_KEY, BTN_TOUCH, 0);
911     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
912 
913     processAxis(conv, EV_KEY, BTN_LEFT, 0);
914     EXPECT_THAT(processSync(conv),
915                 ElementsAre(VariantWith<NotifyMotionArgs>(
916                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
917                             VariantWith<NotifyMotionArgs>(
918                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
919                                           WithPointerCount(1u), WithCoords(50, 100),
920                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
921                                           WithButtonState(0))),
922                             VariantWith<NotifyMotionArgs>(
923                                     WithMotionAction(AMOTION_EVENT_ACTION_UP))));
924 }
925 
926 // Some touchpads sometimes report a button press before they report the finger touching the pad. In
927 // that case we need to wait until the touch comes to report the button press.
TEST_F(CapturedTouchpadEventConverterTest,ButtonPressedBeforeTouch_ReportedOnceTouchOccurs)928 TEST_F(CapturedTouchpadEventConverterTest, ButtonPressedBeforeTouch_ReportedOnceTouchOccurs) {
929     CapturedTouchpadEventConverter conv = createConverter();
930 
931     processAxis(conv, EV_KEY, BTN_LEFT, 1);
932     ASSERT_EQ(0u, processSync(conv).size());
933 
934     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
935     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
936     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
937     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
938     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
939     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
940 
941     EXPECT_THAT(processSync(conv),
942                 ElementsAre(VariantWith<NotifyMotionArgs>(
943                                     WithMotionAction(AMOTION_EVENT_ACTION_DOWN)),
944                             VariantWith<NotifyMotionArgs>(
945                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
946                                           WithPointerCount(1u), WithCoords(50, 100),
947                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
948                                           WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)))));
949 }
950 
951 // When all fingers are lifted from a touchpad, we should release any buttons that are down, since
952 // we won't be able to report them being lifted later if no pointers are present.
TEST_F(CapturedTouchpadEventConverterTest,ButtonReleasedAfterTouchLifts_ReportedWithLift)953 TEST_F(CapturedTouchpadEventConverterTest, ButtonReleasedAfterTouchLifts_ReportedWithLift) {
954     CapturedTouchpadEventConverter conv = createConverter();
955 
956     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
957     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
958     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
959     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
960     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
961     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
962 
963     processAxis(conv, EV_KEY, BTN_LEFT, 1);
964 
965     EXPECT_THAT(processSync(conv),
966                 ElementsAre(VariantWith<NotifyMotionArgs>(
967                                     WithMotionAction(AMOTION_EVENT_ACTION_DOWN)),
968                             VariantWith<NotifyMotionArgs>(
969                                     WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS))));
970 
971     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
972     processAxis(conv, EV_KEY, BTN_TOUCH, 0);
973     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
974     EXPECT_THAT(processSync(conv),
975                 ElementsAre(VariantWith<NotifyMotionArgs>(
976                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
977                             VariantWith<NotifyMotionArgs>(
978                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
979                                           WithPointerCount(1u), WithCoords(50, 100),
980                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
981                                           WithButtonState(0))),
982                             VariantWith<NotifyMotionArgs>(
983                                     WithMotionAction(AMOTION_EVENT_ACTION_UP))));
984 
985     processAxis(conv, EV_KEY, BTN_LEFT, 0);
986     ASSERT_EQ(0u, processSync(conv).size());
987 }
988 
TEST_F(CapturedTouchpadEventConverterTest,MultipleButtonsPressedDuringTouch_ReportedCorrectly)989 TEST_F(CapturedTouchpadEventConverterTest, MultipleButtonsPressedDuringTouch_ReportedCorrectly) {
990     CapturedTouchpadEventConverter conv = createConverter();
991 
992     processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
993     processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
994     processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
995     processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
996     processAxis(conv, EV_KEY, BTN_TOUCH, 1);
997     processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
998 
999     EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
1000                 WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1001 
1002     processAxis(conv, EV_KEY, BTN_LEFT, 1);
1003     EXPECT_THAT(processSync(conv),
1004                 ElementsAre(VariantWith<NotifyMotionArgs>(
1005                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
1006                             VariantWith<NotifyMotionArgs>(
1007                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
1008                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
1009                                           WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)))));
1010 
1011     processAxis(conv, EV_KEY, BTN_RIGHT, 1);
1012     EXPECT_THAT(processSync(conv),
1013                 ElementsAre(VariantWith<NotifyMotionArgs>(
1014                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
1015                             VariantWith<NotifyMotionArgs>(
1016                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
1017                                           WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY),
1018                                           WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY |
1019                                                           AMOTION_EVENT_BUTTON_SECONDARY)))));
1020 
1021     processAxis(conv, EV_KEY, BTN_LEFT, 0);
1022     EXPECT_THAT(processSync(conv),
1023                 ElementsAre(VariantWith<NotifyMotionArgs>(
1024                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
1025                             VariantWith<NotifyMotionArgs>(
1026                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
1027                                           WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
1028                                           WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY)))));
1029 
1030     processAxis(conv, EV_KEY, BTN_RIGHT, 0);
1031     EXPECT_THAT(processSync(conv),
1032                 ElementsAre(VariantWith<NotifyMotionArgs>(
1033                                     WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
1034                             VariantWith<NotifyMotionArgs>(
1035                                     AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
1036                                           WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY),
1037                                           WithButtonState(0)))));
1038 }
1039 
1040 } // namespace android
1041