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