blob: f20c43c5236feb3739c2feb736b4b6d23b56707f [file] [log] [blame]
Harry Cuttsbb24e272023-03-21 10:49:47 +00001/*
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 <gtest/gtest.h>
24#include <linux/input-event-codes.h>
Harry Cutts892bce52023-04-12 16:30:09 +000025#include <linux/input.h>
Harry Cuttsbb24e272023-03-21 10:49:47 +000026#include <utils/StrongPointer.h>
27
28#include "FakeEventHub.h"
29#include "FakeInputReaderPolicy.h"
30#include "InstrumentedInputReader.h"
31#include "TestConstants.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000032#include "TestEventMatchers.h"
Harry Cuttsbb24e272023-03-21 10:49:47 +000033#include "TestInputListener.h"
Harry Cuttsbb24e272023-03-21 10:49:47 +000034
35namespace android {
36
37using testing::AllOf;
Harry Cutts8b70f292024-08-22 18:25:52 +000038using testing::Each;
39using testing::ElementsAre;
40using testing::VariantWith;
Harry Cuttsbb24e272023-03-21 10:49:47 +000041
42class CapturedTouchpadEventConverterTest : public testing::Test {
43public:
44 CapturedTouchpadEventConverterTest()
45 : mFakeEventHub(std::make_unique<FakeEventHub>()),
46 mFakePolicy(sp<FakeInputReaderPolicy>::make()),
47 mReader(mFakeEventHub, mFakePolicy, mFakeListener),
48 mDevice(newDevice()),
49 mDeviceContext(*mDevice, EVENTHUB_ID) {
50 const size_t slotCount = 8;
51 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, 0, slotCount - 1, 0, 0, 0);
52 mAccumulator.configure(mDeviceContext, slotCount, /*usingSlotsProtocol=*/true);
53 }
54
55protected:
56 static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
57 static constexpr int32_t EVENTHUB_ID = 1;
58
59 std::shared_ptr<InputDevice> newDevice() {
60 InputDeviceIdentifier identifier;
61 identifier.name = "device";
62 identifier.location = "USB1";
63 identifier.bus = 0;
64 std::shared_ptr<InputDevice> device =
65 std::make_shared<InputDevice>(mReader.getContext(), DEVICE_ID, /*generation=*/2,
66 identifier);
67 mReader.pushNextDevice(device);
68 mFakeEventHub->addDevice(EVENTHUB_ID, identifier.name, InputDeviceClass::TOUCHPAD,
69 identifier.bus);
70 mReader.loopOnce();
71 return device;
72 }
73
74 void addBasicAxesToEventHub() {
75 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
76 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
77 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, 0, 256, 0, 0, 0);
78 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 1000, 0, 0, 0);
79 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 1000, 0, 0, 0);
80 }
81
82 CapturedTouchpadEventConverter createConverter() {
83 addBasicAxesToEventHub();
84 return CapturedTouchpadEventConverter(*mReader.getContext(), mDeviceContext, mAccumulator,
85 DEVICE_ID);
86 }
87
88 void processAxis(CapturedTouchpadEventConverter& conv, int32_t type, int32_t code,
89 int32_t value) {
90 RawEvent event;
91 event.when = ARBITRARY_TIME;
92 event.readTime = READ_TIME;
93 event.deviceId = EVENTHUB_ID;
94 event.type = type;
95 event.code = code;
96 event.value = value;
97 std::list<NotifyArgs> out = conv.process(event);
98 EXPECT_TRUE(out.empty());
99 }
100
101 std::list<NotifyArgs> processSync(CapturedTouchpadEventConverter& conv) {
102 RawEvent event;
103 event.when = ARBITRARY_TIME;
104 event.readTime = READ_TIME;
105 event.deviceId = EVENTHUB_ID;
106 event.type = EV_SYN;
107 event.code = SYN_REPORT;
108 event.value = 0;
109 return conv.process(event);
110 }
111
112 NotifyMotionArgs processSyncAndExpectSingleMotionArg(CapturedTouchpadEventConverter& conv) {
113 std::list<NotifyArgs> args = processSync(conv);
114 EXPECT_EQ(1u, args.size());
115 return std::get<NotifyMotionArgs>(args.front());
116 }
117
118 std::shared_ptr<FakeEventHub> mFakeEventHub;
119 sp<FakeInputReaderPolicy> mFakePolicy;
120 TestInputListener mFakeListener;
121 InstrumentedInputReader mReader;
122 std::shared_ptr<InputDevice> mDevice;
123 InputDeviceContext mDeviceContext;
124 MultiTouchMotionAccumulator mAccumulator;
125};
126
127TEST_F(CapturedTouchpadEventConverterTest, MotionRanges_allAxesPresent_populatedCorrectly) {
128 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000129 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
Harry Cuttsbb24e272023-03-21 10:49:47 +0000130 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 1100, 0, 0, 35);
131 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 1000, 0, 0, 30);
132 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 900, 0, 0, 25);
133 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 800, 0, 0, 20);
134 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, -3, 4, 0, 0, 0);
135 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, 0, 256, 0, 0, 0);
136 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
137 DEVICE_ID);
138
139 InputDeviceInfo info;
140 conv.populateMotionRanges(info);
141
142 // Most axes should have min, max, and resolution matching the evdev axes.
143 const InputDeviceInfo::MotionRange* posX =
144 info.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHPAD);
145 ASSERT_NE(nullptr, posX);
146 EXPECT_NEAR(0, posX->min, EPSILON);
147 EXPECT_NEAR(4000, posX->max, EPSILON);
148 EXPECT_NEAR(45, posX->resolution, EPSILON);
149
150 const InputDeviceInfo::MotionRange* posY =
151 info.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHPAD);
152 ASSERT_NE(nullptr, posY);
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000153 EXPECT_NEAR(0, posY->min, EPSILON);
154 EXPECT_NEAR(2500, posY->max, EPSILON);
Harry Cuttsbb24e272023-03-21 10:49:47 +0000155 EXPECT_NEAR(40, posY->resolution, EPSILON);
156
157 const InputDeviceInfo::MotionRange* touchMajor =
158 info.getMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR, AINPUT_SOURCE_TOUCHPAD);
159 ASSERT_NE(nullptr, touchMajor);
160 EXPECT_NEAR(0, touchMajor->min, EPSILON);
161 EXPECT_NEAR(1100, touchMajor->max, EPSILON);
162 EXPECT_NEAR(35, touchMajor->resolution, EPSILON);
163
164 const InputDeviceInfo::MotionRange* touchMinor =
165 info.getMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR, AINPUT_SOURCE_TOUCHPAD);
166 ASSERT_NE(nullptr, touchMinor);
167 EXPECT_NEAR(0, touchMinor->min, EPSILON);
168 EXPECT_NEAR(1000, touchMinor->max, EPSILON);
169 EXPECT_NEAR(30, touchMinor->resolution, EPSILON);
170
171 const InputDeviceInfo::MotionRange* toolMajor =
172 info.getMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR, AINPUT_SOURCE_TOUCHPAD);
173 ASSERT_NE(nullptr, toolMajor);
174 EXPECT_NEAR(0, toolMajor->min, EPSILON);
175 EXPECT_NEAR(900, toolMajor->max, EPSILON);
176 EXPECT_NEAR(25, toolMajor->resolution, EPSILON);
177
178 const InputDeviceInfo::MotionRange* toolMinor =
179 info.getMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR, AINPUT_SOURCE_TOUCHPAD);
180 ASSERT_NE(nullptr, toolMinor);
181 EXPECT_NEAR(0, toolMinor->min, EPSILON);
182 EXPECT_NEAR(800, toolMinor->max, EPSILON);
183 EXPECT_NEAR(20, toolMinor->resolution, EPSILON);
184
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000185 // ...except orientation and pressure, which get scaled, and size, which is generated from other
186 // values.
Harry Cuttsbb24e272023-03-21 10:49:47 +0000187 const InputDeviceInfo::MotionRange* orientation =
188 info.getMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, AINPUT_SOURCE_TOUCHPAD);
189 ASSERT_NE(nullptr, orientation);
190 EXPECT_NEAR(-M_PI_2, orientation->min, EPSILON);
191 EXPECT_NEAR(M_PI_2, orientation->max, EPSILON);
192 EXPECT_NEAR(0, orientation->resolution, EPSILON);
193
194 const InputDeviceInfo::MotionRange* pressure =
195 info.getMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_TOUCHPAD);
196 ASSERT_NE(nullptr, pressure);
197 EXPECT_NEAR(0, pressure->min, EPSILON);
198 EXPECT_NEAR(1, pressure->max, EPSILON);
199 EXPECT_NEAR(0, pressure->resolution, EPSILON);
200
201 const InputDeviceInfo::MotionRange* size =
202 info.getMotionRange(AMOTION_EVENT_AXIS_SIZE, AINPUT_SOURCE_TOUCHPAD);
203 ASSERT_NE(nullptr, size);
204 EXPECT_NEAR(0, size->min, EPSILON);
205 EXPECT_NEAR(1, size->max, EPSILON);
206 EXPECT_NEAR(0, size->resolution, EPSILON);
207}
208
209TEST_F(CapturedTouchpadEventConverterTest, MotionRanges_bareMinimumAxesPresent_populatedCorrectly) {
210 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
211 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
212 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
213 DEVICE_ID);
214
215 InputDeviceInfo info;
216 conv.populateMotionRanges(info);
217
218 // Only the bare minimum motion ranges should be reported, and no others (e.g. size shouldn't be
219 // present, since it's generated from axes that aren't provided by this device).
220 EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHPAD));
221 EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHPAD));
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000222 EXPECT_EQ(2u, info.getMotionRanges().size());
Harry Cuttsbb24e272023-03-21 10:49:47 +0000223}
224
225TEST_F(CapturedTouchpadEventConverterTest, OneFinger_motionReportedCorrectly) {
226 CapturedTouchpadEventConverter conv = createConverter();
227
228 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
229 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
230 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
231 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
232
233 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
234 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
235
236 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
237 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000238 WithCoords(50, 100), WithToolType(ToolType::FINGER)));
Harry Cuttsbb24e272023-03-21 10:49:47 +0000239
240 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
241 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 99);
242
243 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
244 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000245 WithCoords(52, 99), WithToolType(ToolType::FINGER)));
Harry Cuttsbb24e272023-03-21 10:49:47 +0000246
247 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
248 processAxis(conv, EV_KEY, BTN_TOUCH, 0);
249 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
250
251 std::list<NotifyArgs> args = processSync(conv);
Harry Cutts8b70f292024-08-22 18:25:52 +0000252 EXPECT_THAT(args,
253 ElementsAre(VariantWith<NotifyMotionArgs>(
254 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
255 VariantWith<NotifyMotionArgs>(
256 WithMotionAction(AMOTION_EVENT_ACTION_UP))));
257 EXPECT_THAT(args,
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000258 Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(52, 99), WithPointerCount(1u),
259 WithToolType(ToolType::FINGER)))));
Harry Cuttsbb24e272023-03-21 10:49:47 +0000260}
261
262TEST_F(CapturedTouchpadEventConverterTest, OneFinger_touchDimensionsPassedThrough) {
263 addBasicAxesToEventHub();
264 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 1000, 0, 0, 0);
265 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 1000, 0, 0, 0);
266 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
267 DEVICE_ID);
268
269 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
270 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
271 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MAJOR, 250);
272 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MINOR, 120);
273 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 400);
274 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MINOR, 200);
275
276 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
277 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
278
279 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
280 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
281 WithTouchDimensions(250, 120), WithToolDimensions(400, 200)));
282}
283
284TEST_F(CapturedTouchpadEventConverterTest, OneFinger_orientationCalculatedCorrectly) {
285 addBasicAxesToEventHub();
286 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, -3, 4, 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_ORIENTATION, -3);
293 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
294 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
295
296 EXPECT_NEAR(-3 * M_PI / 8,
297 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
298 AMOTION_EVENT_AXIS_ORIENTATION),
299 EPSILON);
300
301 processAxis(conv, EV_ABS, ABS_MT_ORIENTATION, 0);
302
303 EXPECT_NEAR(0,
304 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
305 AMOTION_EVENT_AXIS_ORIENTATION),
306 EPSILON);
307
308 processAxis(conv, EV_ABS, ABS_MT_ORIENTATION, 4);
309
310 EXPECT_NEAR(M_PI / 2,
311 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
312 AMOTION_EVENT_AXIS_ORIENTATION),
313 EPSILON);
314}
315
316TEST_F(CapturedTouchpadEventConverterTest, OneFinger_pressureScaledCorrectly) {
317 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
318 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
319 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, 0, 256, 0, 0, 0);
320 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
321 DEVICE_ID);
322
323 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
324 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
325 processAxis(conv, EV_ABS, ABS_MT_PRESSURE, 128);
326 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
327 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
328
329 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv), WithPressure(0.5));
330}
331
332TEST_F(CapturedTouchpadEventConverterTest,
333 OneFinger_withAllSizeAxes_sizeCalculatedFromTouchMajorMinorAverage) {
334 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
335 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
336 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 256, 0, 0, 0);
337 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 256, 0, 0, 0);
338 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
339 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 256, 0, 0, 0);
340 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
341 DEVICE_ID);
342
343 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
344 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
345 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MAJOR, 138);
346 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MINOR, 118);
347 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 200);
348 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MINOR, 210);
349 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
350 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
351
352 EXPECT_NEAR(0.5,
353 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
354 AMOTION_EVENT_AXIS_SIZE),
355 EPSILON);
356}
357
358TEST_F(CapturedTouchpadEventConverterTest,
359 OneFinger_withMajorDimensionsOnly_sizeCalculatedFromTouchMajor) {
360 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
361 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
362 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 256, 0, 0, 0);
363 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
364 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
365 DEVICE_ID);
366
367 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
368 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
369 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MAJOR, 128);
370 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 200);
371 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
372 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
373
374 EXPECT_NEAR(0.5,
375 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
376 AMOTION_EVENT_AXIS_SIZE),
377 EPSILON);
378}
379
380TEST_F(CapturedTouchpadEventConverterTest,
381 OneFinger_withToolDimensionsOnly_sizeCalculatedFromToolMajorMinorAverage) {
382 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
383 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
384 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
385 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 256, 0, 0, 0);
386 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
387 DEVICE_ID);
388
389 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
390 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
391 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 138);
392 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MINOR, 118);
393 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
394 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
395
396 EXPECT_NEAR(0.5,
397 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
398 AMOTION_EVENT_AXIS_SIZE),
399 EPSILON);
400}
401
402TEST_F(CapturedTouchpadEventConverterTest,
403 OneFinger_withToolMajorOnly_sizeCalculatedFromTouchMajor) {
404 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
405 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
406 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 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, 128);
413 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
414 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
415
416 EXPECT_NEAR(0.5,
417 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
418 AMOTION_EVENT_AXIS_SIZE),
419 EPSILON);
420}
421
Harry Cutts892bce52023-04-12 16:30:09 +0000422TEST_F(CapturedTouchpadEventConverterTest, OnePalm_neverReported) {
423 addBasicAxesToEventHub();
424 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
425 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
426 DEVICE_ID);
427
428 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
429 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
430 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
431 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
432 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
433 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
434 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
435
436 EXPECT_EQ(0u, processSync(conv).size());
437
438 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
439
440 EXPECT_EQ(0u, processSync(conv).size());
441
442 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
443 processAxis(conv, EV_KEY, BTN_TOUCH, 0);
444 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
445
446 EXPECT_EQ(0u, processSync(conv).size());
447}
448
449TEST_F(CapturedTouchpadEventConverterTest, FingerTurningIntoPalm_cancelled) {
450 addBasicAxesToEventHub();
451 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
452 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
453 DEVICE_ID);
454
455 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
456 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
457 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
458 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
459 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
460 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
461 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
462
463 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
464 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::FINGER),
465 WithPointerCount(1u)));
466
467 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
468 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
469
470 std::list<NotifyArgs> args = processSync(conv);
471 ASSERT_EQ(2u, args.size());
472 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
473 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u)));
474 args.pop_front();
475 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
476 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL), WithPointerCount(1u)));
477
478 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
479
480 EXPECT_EQ(0u, processSync(conv).size());
481
482 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
483 processAxis(conv, EV_KEY, BTN_TOUCH, 0);
484 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
485
486 EXPECT_EQ(0u, processSync(conv).size());
487}
488
489TEST_F(CapturedTouchpadEventConverterTest, PalmTurningIntoFinger_reported) {
490 addBasicAxesToEventHub();
491 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
492 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
493 DEVICE_ID);
494
495 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
496 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
497 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
498 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
499 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
500 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
501 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
502
503 EXPECT_EQ(0u, processSync(conv).size());
504
505 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
506 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
507
508 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
509 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000510 WithCoords(51, 100)));
Harry Cutts892bce52023-04-12 16:30:09 +0000511
512 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
513
514 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
515 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000516 WithCoords(52, 100)));
Harry Cutts892bce52023-04-12 16:30:09 +0000517}
518
519TEST_F(CapturedTouchpadEventConverterTest, FingerArrivingAfterPalm_onlyFingerReported) {
520 addBasicAxesToEventHub();
521 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
522 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
523 DEVICE_ID);
524
525 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
526 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
527 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
528 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
529 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
530 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
531 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
532
533 EXPECT_EQ(0u, processSync(conv).size());
534
535 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
536 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
537 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 100);
538 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 150);
539 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
540 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
541 processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
542
543 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
544 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
545 WithCoords(100, 150)));
546
547 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
548 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
549 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 102);
550 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
551 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 98);
552 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 148);
553
554 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
555 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000556 WithCoords(98, 148)));
Harry Cutts892bce52023-04-12 16:30:09 +0000557}
558
559TEST_F(CapturedTouchpadEventConverterTest, FingerAndFingerTurningIntoPalm_partiallyCancelled) {
560 addBasicAxesToEventHub();
561 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
562 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
563 DEVICE_ID);
564
565 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
566 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
567 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
568 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
569
570 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
571 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
572 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 250);
573 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
574
575 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
576 processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
577
Harry Cutts8b70f292024-08-22 18:25:52 +0000578 EXPECT_THAT(processSync(conv),
579 ElementsAre(VariantWith<NotifyMotionArgs>(
580 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
581 WithPointerCount(1u), WithToolType(ToolType::FINGER))),
582 VariantWith<NotifyMotionArgs>(
583 AllOf(WithMotionAction(
584 AMOTION_EVENT_ACTION_POINTER_DOWN |
585 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
586 WithPointerCount(2u),
587 WithPointerToolType(0, ToolType::FINGER),
588 WithPointerToolType(1, ToolType::FINGER)))));
Harry Cutts892bce52023-04-12 16:30:09 +0000589
590 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
591 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
592
593 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
594 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 251);
595 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
596
Harry Cutts8b70f292024-08-22 18:25:52 +0000597 std::list<NotifyArgs> args = processSync(conv);
598 EXPECT_THAT(args,
599 ElementsAre(VariantWith<NotifyMotionArgs>(
600 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
601 VariantWith<NotifyMotionArgs>(
602 AllOf(WithMotionAction(
603 AMOTION_EVENT_ACTION_POINTER_UP |
604 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
605 WithFlags(AMOTION_EVENT_FLAG_CANCELED)))));
606 EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithPointerCount(2u))));
Harry Cutts892bce52023-04-12 16:30:09 +0000607}
608
609TEST_F(CapturedTouchpadEventConverterTest, FingerAndPalmTurningIntoFinger_reported) {
610 addBasicAxesToEventHub();
611 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_PALM, 0, 0, 0);
612 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
613 DEVICE_ID);
614
615 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
616 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
617 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
618 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
619
620 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
621 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
622 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 250);
623 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
624
625 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
626 processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
627
628 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
629 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
630 WithToolType(ToolType::FINGER)));
631
632 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
633 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 51);
634
635 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
636 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 251);
637 processAxis(conv, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
638
Harry Cutts8b70f292024-08-22 18:25:52 +0000639 EXPECT_THAT(processSync(conv),
640 ElementsAre(VariantWith<NotifyMotionArgs>(
641 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
642 WithPointerCount(1u))),
643 VariantWith<NotifyMotionArgs>(
644 AllOf(WithMotionAction(
645 AMOTION_EVENT_ACTION_POINTER_DOWN |
646 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
647 WithPointerCount(2u)))));
Harry Cutts892bce52023-04-12 16:30:09 +0000648}
649
Harry Cuttsbb24e272023-03-21 10:49:47 +0000650TEST_F(CapturedTouchpadEventConverterTest, TwoFingers_motionReportedCorrectly) {
651 CapturedTouchpadEventConverter conv = createConverter();
652
653 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
654 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
655 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
656 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
657
658 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
659 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
660
661 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
662 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000663 WithCoords(50, 100), WithToolType(ToolType::FINGER)));
Harry Cuttsbb24e272023-03-21 10:49:47 +0000664
665 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
666 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
667 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 99);
668
669 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
670 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
671 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 250);
672 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 200);
673
674 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
675 processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
676
Harry Cutts8b70f292024-08-22 18:25:52 +0000677 EXPECT_THAT(processSync(conv),
678 ElementsAre(VariantWith<NotifyMotionArgs>(
679 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
680 WithPointerCount(1u), WithCoords(52, 99),
681 WithToolType(ToolType::FINGER))),
682 VariantWith<NotifyMotionArgs>(
683 AllOf(WithMotionAction(
684 AMOTION_EVENT_ACTION_POINTER_DOWN |
685 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
686 WithPointerCount(2u), WithPointerCoords(0, 52, 99),
687 WithPointerCoords(1, 250, 200),
688 WithPointerToolType(0, ToolType::FINGER),
689 WithPointerToolType(1, ToolType::FINGER)))));
Harry Cuttsbb24e272023-03-21 10:49:47 +0000690
691 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
692 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
693 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
694 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 255);
695 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 202);
696
697 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
698 processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
699
Harry Cutts8b70f292024-08-22 18:25:52 +0000700 std::list<NotifyArgs> args = processSync(conv);
701 EXPECT_THAT(args,
702 ElementsAre(VariantWith<NotifyMotionArgs>(
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000703 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
704 VariantWith<NotifyMotionArgs>(WithMotionAction(
705 AMOTION_EVENT_ACTION_POINTER_UP |
706 0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT))));
Harry Cutts8b70f292024-08-22 18:25:52 +0000707 EXPECT_THAT(args,
708 Each(VariantWith<NotifyMotionArgs>(
709 AllOf(WithPointerCount(2u), WithPointerCoords(0, 52, 99),
Harry Cuttscdb5a7e2024-09-09 21:55:25 +0000710 WithPointerCoords(1, 255, 202),
Harry Cutts8b70f292024-08-22 18:25:52 +0000711 WithPointerToolType(1, ToolType::FINGER),
712 WithPointerToolType(0, ToolType::FINGER)))));
Harry Cuttsbb24e272023-03-21 10:49:47 +0000713
714 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
715 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
716 processAxis(conv, EV_KEY, BTN_TOUCH, 0);
717
718 args = processSync(conv);
Harry Cutts8b70f292024-08-22 18:25:52 +0000719 EXPECT_THAT(args,
720 ElementsAre(VariantWith<NotifyMotionArgs>(
721 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
722 VariantWith<NotifyMotionArgs>(
723 WithMotionAction(AMOTION_EVENT_ACTION_UP))));
724 EXPECT_THAT(args,
725 Each(VariantWith<NotifyMotionArgs>(AllOf(WithPointerCount(1u), WithCoords(255, 202),
726 WithToolType(ToolType::FINGER)))));
Harry Cuttsbb24e272023-03-21 10:49:47 +0000727}
728
729// Pointer IDs max out at 31, and so must be reused once a touch is lifted to avoid running out.
730TEST_F(CapturedTouchpadEventConverterTest, PointerIdsReusedAfterLift) {
731 CapturedTouchpadEventConverter conv = createConverter();
732
733 // Put down two fingers, which should get IDs 0 and 1.
734 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
735 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
736 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 10);
737 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
738 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
739 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 20);
740
741 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
742 processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
743
Harry Cutts8b70f292024-08-22 18:25:52 +0000744 EXPECT_THAT(processSync(conv),
745 ElementsAre(VariantWith<NotifyMotionArgs>(
746 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
747 WithPointerCount(1u),
748 WithPointerId(/*index=*/0, /*id=*/0))),
749 VariantWith<NotifyMotionArgs>(
750 AllOf(WithMotionAction(
751 AMOTION_EVENT_ACTION_POINTER_DOWN |
752 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
753 WithPointerCount(2u),
754 WithPointerId(/*index=*/0, /*id=*/0),
755 WithPointerId(/*index=*/1, /*id=*/1)))));
Harry Cuttsbb24e272023-03-21 10:49:47 +0000756
757 // Lift the finger in slot 0, freeing up pointer ID 0...
758 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
759 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
760
761 // ...and simultaneously add a finger in slot 2.
762 processAxis(conv, EV_ABS, ABS_MT_SLOT, 2);
763 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 3);
764 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 30);
765
Harry Cutts8b70f292024-08-22 18:25:52 +0000766 std::list<NotifyArgs> args = processSync(conv);
Harry Cuttsbb24e272023-03-21 10:49:47 +0000767 // Slot 1 being present will result in a MOVE event, even though it hasn't actually moved (see
768 // comments in CapturedTouchpadEventConverter::sync).
Harry Cutts8b70f292024-08-22 18:25:52 +0000769 EXPECT_THAT(args,
770 ElementsAre(VariantWith<NotifyMotionArgs>(
771 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
772 WithPointerId(/*index=*/0, /*id=*/0),
773 WithPointerId(/*index=*/1, /*id=*/1))),
774 VariantWith<NotifyMotionArgs>(
775 AllOf(WithMotionAction(
776 AMOTION_EVENT_ACTION_POINTER_UP |
777 0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
778 WithPointerId(/*index=*/0, /*id=*/0),
779 WithPointerId(/*index=*/1, /*id=*/1))),
780 // Slot 0 being lifted causes the finger from slot 1 to move up to index
781 // 0, but keep its previous ID. The new finger in slot 2 should take ID
782 // 0, which was just freed up.
783 VariantWith<NotifyMotionArgs>(
784 AllOf(WithMotionAction(
785 AMOTION_EVENT_ACTION_POINTER_DOWN |
786 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
787 WithPointerId(/*index=*/0, /*id=*/1),
788 WithPointerId(/*index=*/1, /*id=*/0)))));
789 EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithPointerCount(2u))));
Harry Cuttsbb24e272023-03-21 10:49:47 +0000790}
791
Harry Cutts23c8dff2023-05-10 17:39:59 +0000792// Motion events without any pointers are invalid, so when a button press is reported in the same
793// frame as a touch down, the button press must be reported second. Similarly with a button release
794// and a touch lift.
795TEST_F(CapturedTouchpadEventConverterTest,
796 ButtonPressedAndReleasedInSameFrameAsTouch_ReportedWithPointers) {
797 CapturedTouchpadEventConverter conv = createConverter();
798
799 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
800 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
801 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
802 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
803 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
804 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
805
806 processAxis(conv, EV_KEY, BTN_LEFT, 1);
807
Harry Cutts8b70f292024-08-22 18:25:52 +0000808 EXPECT_THAT(processSync(conv),
809 ElementsAre(VariantWith<NotifyMotionArgs>(
810 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)),
811 VariantWith<NotifyMotionArgs>(
812 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
813 WithPointerCount(1u), WithCoords(50, 100),
814 WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
815 WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)))));
Harry Cutts23c8dff2023-05-10 17:39:59 +0000816
817 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
818 processAxis(conv, EV_KEY, BTN_TOUCH, 0);
819 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
820
821 processAxis(conv, EV_KEY, BTN_LEFT, 0);
Harry Cutts8b70f292024-08-22 18:25:52 +0000822 EXPECT_THAT(processSync(conv),
823 ElementsAre(VariantWith<NotifyMotionArgs>(
824 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
825 VariantWith<NotifyMotionArgs>(
826 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
827 WithPointerCount(1u), WithCoords(50, 100),
828 WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
829 WithButtonState(0))),
830 VariantWith<NotifyMotionArgs>(
831 WithMotionAction(AMOTION_EVENT_ACTION_UP))));
Harry Cutts23c8dff2023-05-10 17:39:59 +0000832}
833
834// Some touchpads sometimes report a button press before they report the finger touching the pad. In
835// that case we need to wait until the touch comes to report the button press.
836TEST_F(CapturedTouchpadEventConverterTest, ButtonPressedBeforeTouch_ReportedOnceTouchOccurs) {
837 CapturedTouchpadEventConverter conv = createConverter();
838
839 processAxis(conv, EV_KEY, BTN_LEFT, 1);
840 ASSERT_EQ(0u, processSync(conv).size());
841
842 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
843 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
844 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
845 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
846 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
847 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
848
Harry Cutts8b70f292024-08-22 18:25:52 +0000849 EXPECT_THAT(processSync(conv),
850 ElementsAre(VariantWith<NotifyMotionArgs>(
851 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)),
852 VariantWith<NotifyMotionArgs>(
853 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
854 WithPointerCount(1u), WithCoords(50, 100),
855 WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
856 WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)))));
Harry Cutts23c8dff2023-05-10 17:39:59 +0000857}
858
859// When all fingers are lifted from a touchpad, we should release any buttons that are down, since
860// we won't be able to report them being lifted later if no pointers are present.
861TEST_F(CapturedTouchpadEventConverterTest, ButtonReleasedAfterTouchLifts_ReportedWithLift) {
862 CapturedTouchpadEventConverter conv = createConverter();
863
864 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
865 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
866 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
867 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
868 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
869 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
870
871 processAxis(conv, EV_KEY, BTN_LEFT, 1);
872
Harry Cutts8b70f292024-08-22 18:25:52 +0000873 EXPECT_THAT(processSync(conv),
874 ElementsAre(VariantWith<NotifyMotionArgs>(
875 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)),
876 VariantWith<NotifyMotionArgs>(
877 WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS))));
Harry Cutts23c8dff2023-05-10 17:39:59 +0000878
879 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
880 processAxis(conv, EV_KEY, BTN_TOUCH, 0);
881 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
Harry Cutts8b70f292024-08-22 18:25:52 +0000882 EXPECT_THAT(processSync(conv),
883 ElementsAre(VariantWith<NotifyMotionArgs>(
884 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
885 VariantWith<NotifyMotionArgs>(
886 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
887 WithPointerCount(1u), WithCoords(50, 100),
888 WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
889 WithButtonState(0))),
890 VariantWith<NotifyMotionArgs>(
891 WithMotionAction(AMOTION_EVENT_ACTION_UP))));
Harry Cutts23c8dff2023-05-10 17:39:59 +0000892
893 processAxis(conv, EV_KEY, BTN_LEFT, 0);
894 ASSERT_EQ(0u, processSync(conv).size());
895}
896
897TEST_F(CapturedTouchpadEventConverterTest, MultipleButtonsPressedDuringTouch_ReportedCorrectly) {
898 CapturedTouchpadEventConverter conv = createConverter();
899
900 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
901 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
902 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
903 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
904 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
905 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
906
907 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
908 WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
909
910 processAxis(conv, EV_KEY, BTN_LEFT, 1);
Harry Cutts8b70f292024-08-22 18:25:52 +0000911 EXPECT_THAT(processSync(conv),
912 ElementsAre(VariantWith<NotifyMotionArgs>(
913 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
914 VariantWith<NotifyMotionArgs>(
915 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
916 WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
917 WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)))));
Harry Cutts23c8dff2023-05-10 17:39:59 +0000918
919 processAxis(conv, EV_KEY, BTN_RIGHT, 1);
Harry Cutts8b70f292024-08-22 18:25:52 +0000920 EXPECT_THAT(processSync(conv),
921 ElementsAre(VariantWith<NotifyMotionArgs>(
922 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
923 VariantWith<NotifyMotionArgs>(
924 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
925 WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY),
926 WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY |
927 AMOTION_EVENT_BUTTON_SECONDARY)))));
Harry Cutts23c8dff2023-05-10 17:39:59 +0000928
929 processAxis(conv, EV_KEY, BTN_LEFT, 0);
Harry Cutts8b70f292024-08-22 18:25:52 +0000930 EXPECT_THAT(processSync(conv),
931 ElementsAre(VariantWith<NotifyMotionArgs>(
932 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
933 VariantWith<NotifyMotionArgs>(
934 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
935 WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
936 WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY)))));
Harry Cutts23c8dff2023-05-10 17:39:59 +0000937
938 processAxis(conv, EV_KEY, BTN_RIGHT, 0);
Harry Cutts8b70f292024-08-22 18:25:52 +0000939 EXPECT_THAT(processSync(conv),
940 ElementsAre(VariantWith<NotifyMotionArgs>(
941 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
942 VariantWith<NotifyMotionArgs>(
943 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
944 WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY),
945 WithButtonState(0)))));
Harry Cutts23c8dff2023-05-10 17:39:59 +0000946}
947
Harry Cuttsbb24e272023-03-21 10:49:47 +0000948} // namespace android