blob: 694641cf87f38a863a90adcc302fa44f09cc2118 [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>
25#include <utils/StrongPointer.h>
26
27#include "FakeEventHub.h"
28#include "FakeInputReaderPolicy.h"
29#include "InstrumentedInputReader.h"
30#include "TestConstants.h"
31#include "TestInputListener.h"
32#include "TestInputListenerMatchers.h"
33
34namespace android {
35
36using testing::AllOf;
37
38class CapturedTouchpadEventConverterTest : public testing::Test {
39public:
40 CapturedTouchpadEventConverterTest()
41 : mFakeEventHub(std::make_unique<FakeEventHub>()),
42 mFakePolicy(sp<FakeInputReaderPolicy>::make()),
43 mReader(mFakeEventHub, mFakePolicy, mFakeListener),
44 mDevice(newDevice()),
45 mDeviceContext(*mDevice, EVENTHUB_ID) {
46 const size_t slotCount = 8;
47 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, 0, slotCount - 1, 0, 0, 0);
48 mAccumulator.configure(mDeviceContext, slotCount, /*usingSlotsProtocol=*/true);
49 }
50
51protected:
52 static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
53 static constexpr int32_t EVENTHUB_ID = 1;
54
55 std::shared_ptr<InputDevice> newDevice() {
56 InputDeviceIdentifier identifier;
57 identifier.name = "device";
58 identifier.location = "USB1";
59 identifier.bus = 0;
60 std::shared_ptr<InputDevice> device =
61 std::make_shared<InputDevice>(mReader.getContext(), DEVICE_ID, /*generation=*/2,
62 identifier);
63 mReader.pushNextDevice(device);
64 mFakeEventHub->addDevice(EVENTHUB_ID, identifier.name, InputDeviceClass::TOUCHPAD,
65 identifier.bus);
66 mReader.loopOnce();
67 return device;
68 }
69
70 void addBasicAxesToEventHub() {
71 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
72 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
73 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, 0, 256, 0, 0, 0);
74 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 1000, 0, 0, 0);
75 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 1000, 0, 0, 0);
76 }
77
78 CapturedTouchpadEventConverter createConverter() {
79 addBasicAxesToEventHub();
80 return CapturedTouchpadEventConverter(*mReader.getContext(), mDeviceContext, mAccumulator,
81 DEVICE_ID);
82 }
83
84 void processAxis(CapturedTouchpadEventConverter& conv, int32_t type, int32_t code,
85 int32_t value) {
86 RawEvent event;
87 event.when = ARBITRARY_TIME;
88 event.readTime = READ_TIME;
89 event.deviceId = EVENTHUB_ID;
90 event.type = type;
91 event.code = code;
92 event.value = value;
93 std::list<NotifyArgs> out = conv.process(event);
94 EXPECT_TRUE(out.empty());
95 }
96
97 std::list<NotifyArgs> processSync(CapturedTouchpadEventConverter& conv) {
98 RawEvent event;
99 event.when = ARBITRARY_TIME;
100 event.readTime = READ_TIME;
101 event.deviceId = EVENTHUB_ID;
102 event.type = EV_SYN;
103 event.code = SYN_REPORT;
104 event.value = 0;
105 return conv.process(event);
106 }
107
108 NotifyMotionArgs processSyncAndExpectSingleMotionArg(CapturedTouchpadEventConverter& conv) {
109 std::list<NotifyArgs> args = processSync(conv);
110 EXPECT_EQ(1u, args.size());
111 return std::get<NotifyMotionArgs>(args.front());
112 }
113
114 std::shared_ptr<FakeEventHub> mFakeEventHub;
115 sp<FakeInputReaderPolicy> mFakePolicy;
116 TestInputListener mFakeListener;
117 InstrumentedInputReader mReader;
118 std::shared_ptr<InputDevice> mDevice;
119 InputDeviceContext mDeviceContext;
120 MultiTouchMotionAccumulator mAccumulator;
121};
122
123TEST_F(CapturedTouchpadEventConverterTest, MotionRanges_allAxesPresent_populatedCorrectly) {
124 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
125 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
126 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 1100, 0, 0, 35);
127 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 1000, 0, 0, 30);
128 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 900, 0, 0, 25);
129 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 800, 0, 0, 20);
130 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, -3, 4, 0, 0, 0);
131 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, 0, 256, 0, 0, 0);
132 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
133 DEVICE_ID);
134
135 InputDeviceInfo info;
136 conv.populateMotionRanges(info);
137
138 // Most axes should have min, max, and resolution matching the evdev axes.
139 const InputDeviceInfo::MotionRange* posX =
140 info.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHPAD);
141 ASSERT_NE(nullptr, posX);
142 EXPECT_NEAR(0, posX->min, EPSILON);
143 EXPECT_NEAR(4000, posX->max, EPSILON);
144 EXPECT_NEAR(45, posX->resolution, EPSILON);
145
146 const InputDeviceInfo::MotionRange* posY =
147 info.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHPAD);
148 ASSERT_NE(nullptr, posY);
149 EXPECT_NEAR(0, posY->min, EPSILON);
150 EXPECT_NEAR(2500, posY->max, EPSILON);
151 EXPECT_NEAR(40, posY->resolution, EPSILON);
152
153 const InputDeviceInfo::MotionRange* touchMajor =
154 info.getMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR, AINPUT_SOURCE_TOUCHPAD);
155 ASSERT_NE(nullptr, touchMajor);
156 EXPECT_NEAR(0, touchMajor->min, EPSILON);
157 EXPECT_NEAR(1100, touchMajor->max, EPSILON);
158 EXPECT_NEAR(35, touchMajor->resolution, EPSILON);
159
160 const InputDeviceInfo::MotionRange* touchMinor =
161 info.getMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR, AINPUT_SOURCE_TOUCHPAD);
162 ASSERT_NE(nullptr, touchMinor);
163 EXPECT_NEAR(0, touchMinor->min, EPSILON);
164 EXPECT_NEAR(1000, touchMinor->max, EPSILON);
165 EXPECT_NEAR(30, touchMinor->resolution, EPSILON);
166
167 const InputDeviceInfo::MotionRange* toolMajor =
168 info.getMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR, AINPUT_SOURCE_TOUCHPAD);
169 ASSERT_NE(nullptr, toolMajor);
170 EXPECT_NEAR(0, toolMajor->min, EPSILON);
171 EXPECT_NEAR(900, toolMajor->max, EPSILON);
172 EXPECT_NEAR(25, toolMajor->resolution, EPSILON);
173
174 const InputDeviceInfo::MotionRange* toolMinor =
175 info.getMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR, AINPUT_SOURCE_TOUCHPAD);
176 ASSERT_NE(nullptr, toolMinor);
177 EXPECT_NEAR(0, toolMinor->min, EPSILON);
178 EXPECT_NEAR(800, toolMinor->max, EPSILON);
179 EXPECT_NEAR(20, toolMinor->resolution, EPSILON);
180
181 // ...except orientation and pressure, which get scaled, and size, which is generated from other
182 // values.
183 const InputDeviceInfo::MotionRange* orientation =
184 info.getMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, AINPUT_SOURCE_TOUCHPAD);
185 ASSERT_NE(nullptr, orientation);
186 EXPECT_NEAR(-M_PI_2, orientation->min, EPSILON);
187 EXPECT_NEAR(M_PI_2, orientation->max, EPSILON);
188 EXPECT_NEAR(0, orientation->resolution, EPSILON);
189
190 const InputDeviceInfo::MotionRange* pressure =
191 info.getMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_TOUCHPAD);
192 ASSERT_NE(nullptr, pressure);
193 EXPECT_NEAR(0, pressure->min, EPSILON);
194 EXPECT_NEAR(1, pressure->max, EPSILON);
195 EXPECT_NEAR(0, pressure->resolution, EPSILON);
196
197 const InputDeviceInfo::MotionRange* size =
198 info.getMotionRange(AMOTION_EVENT_AXIS_SIZE, AINPUT_SOURCE_TOUCHPAD);
199 ASSERT_NE(nullptr, size);
200 EXPECT_NEAR(0, size->min, EPSILON);
201 EXPECT_NEAR(1, size->max, EPSILON);
202 EXPECT_NEAR(0, size->resolution, EPSILON);
203}
204
205TEST_F(CapturedTouchpadEventConverterTest, MotionRanges_bareMinimumAxesPresent_populatedCorrectly) {
206 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
207 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
208 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
209 DEVICE_ID);
210
211 InputDeviceInfo info;
212 conv.populateMotionRanges(info);
213
214 // Only the bare minimum motion ranges should be reported, and no others (e.g. size shouldn't be
215 // present, since it's generated from axes that aren't provided by this device).
216 EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHPAD));
217 EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHPAD));
218 EXPECT_EQ(2u, info.getMotionRanges().size());
219}
220
221TEST_F(CapturedTouchpadEventConverterTest, OneFinger_motionReportedCorrectly) {
222 CapturedTouchpadEventConverter conv = createConverter();
223
224 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
225 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
226 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
227 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
228
229 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
230 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
231
232 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
233 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
234 WithCoords(50, 100), WithToolType(ToolType::FINGER)));
235
236 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
237 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 99);
238
239 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
240 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
241 WithCoords(52, 99), WithToolType(ToolType::FINGER)));
242
243 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
244 processAxis(conv, EV_KEY, BTN_TOUCH, 0);
245 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
246
247 std::list<NotifyArgs> args = processSync(conv);
248 ASSERT_EQ(2u, args.size());
249 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
250 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
251 WithCoords(52, 99), WithToolType(ToolType::FINGER)));
252 args.pop_front();
253 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
254 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithPointerCount(1u),
255 WithCoords(52, 99), WithToolType(ToolType::FINGER)));
256}
257
258TEST_F(CapturedTouchpadEventConverterTest, OneFinger_touchDimensionsPassedThrough) {
259 addBasicAxesToEventHub();
260 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 1000, 0, 0, 0);
261 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 1000, 0, 0, 0);
262 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
263 DEVICE_ID);
264
265 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
266 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
267 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MAJOR, 250);
268 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MINOR, 120);
269 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 400);
270 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MINOR, 200);
271
272 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
273 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
274
275 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
276 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
277 WithTouchDimensions(250, 120), WithToolDimensions(400, 200)));
278}
279
280TEST_F(CapturedTouchpadEventConverterTest, OneFinger_orientationCalculatedCorrectly) {
281 addBasicAxesToEventHub();
282 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, -3, 4, 0, 0, 0);
283 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
284 DEVICE_ID);
285
286 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
287 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
288 processAxis(conv, EV_ABS, ABS_MT_ORIENTATION, -3);
289 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
290 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
291
292 EXPECT_NEAR(-3 * M_PI / 8,
293 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
294 AMOTION_EVENT_AXIS_ORIENTATION),
295 EPSILON);
296
297 processAxis(conv, EV_ABS, ABS_MT_ORIENTATION, 0);
298
299 EXPECT_NEAR(0,
300 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
301 AMOTION_EVENT_AXIS_ORIENTATION),
302 EPSILON);
303
304 processAxis(conv, EV_ABS, ABS_MT_ORIENTATION, 4);
305
306 EXPECT_NEAR(M_PI / 2,
307 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
308 AMOTION_EVENT_AXIS_ORIENTATION),
309 EPSILON);
310}
311
312TEST_F(CapturedTouchpadEventConverterTest, OneFinger_pressureScaledCorrectly) {
313 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
314 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
315 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, 0, 256, 0, 0, 0);
316 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
317 DEVICE_ID);
318
319 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
320 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
321 processAxis(conv, EV_ABS, ABS_MT_PRESSURE, 128);
322 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
323 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
324
325 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv), WithPressure(0.5));
326}
327
328TEST_F(CapturedTouchpadEventConverterTest,
329 OneFinger_withAllSizeAxes_sizeCalculatedFromTouchMajorMinorAverage) {
330 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
331 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
332 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 256, 0, 0, 0);
333 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 256, 0, 0, 0);
334 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
335 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 256, 0, 0, 0);
336 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
337 DEVICE_ID);
338
339 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
340 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
341 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MAJOR, 138);
342 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MINOR, 118);
343 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 200);
344 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MINOR, 210);
345 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
346 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
347
348 EXPECT_NEAR(0.5,
349 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
350 AMOTION_EVENT_AXIS_SIZE),
351 EPSILON);
352}
353
354TEST_F(CapturedTouchpadEventConverterTest,
355 OneFinger_withMajorDimensionsOnly_sizeCalculatedFromTouchMajor) {
356 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
357 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
358 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 256, 0, 0, 0);
359 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
360 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
361 DEVICE_ID);
362
363 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
364 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
365 processAxis(conv, EV_ABS, ABS_MT_TOUCH_MAJOR, 128);
366 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 200);
367 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
368 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
369
370 EXPECT_NEAR(0.5,
371 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
372 AMOTION_EVENT_AXIS_SIZE),
373 EPSILON);
374}
375
376TEST_F(CapturedTouchpadEventConverterTest,
377 OneFinger_withToolDimensionsOnly_sizeCalculatedFromToolMajorMinorAverage) {
378 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
379 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
380 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
381 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, 0, 256, 0, 0, 0);
382 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
383 DEVICE_ID);
384
385 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
386 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
387 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 138);
388 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MINOR, 118);
389 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
390 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
391
392 EXPECT_NEAR(0.5,
393 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
394 AMOTION_EVENT_AXIS_SIZE),
395 EPSILON);
396}
397
398TEST_F(CapturedTouchpadEventConverterTest,
399 OneFinger_withToolMajorOnly_sizeCalculatedFromTouchMajor) {
400 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
401 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
402 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 256, 0, 0, 0);
403 CapturedTouchpadEventConverter conv(*mReader.getContext(), mDeviceContext, mAccumulator,
404 DEVICE_ID);
405
406 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
407 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
408 processAxis(conv, EV_ABS, ABS_MT_WIDTH_MAJOR, 128);
409 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
410 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
411
412 EXPECT_NEAR(0.5,
413 processSyncAndExpectSingleMotionArg(conv).pointerCoords[0].getAxisValue(
414 AMOTION_EVENT_AXIS_SIZE),
415 EPSILON);
416}
417
418TEST_F(CapturedTouchpadEventConverterTest, TwoFingers_motionReportedCorrectly) {
419 CapturedTouchpadEventConverter conv = createConverter();
420
421 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
422 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
423 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
424 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
425
426 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
427 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
428
429 EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
430 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
431 WithCoords(50, 100), WithToolType(ToolType::FINGER)));
432
433 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
434 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
435 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 99);
436
437 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
438 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
439 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 250);
440 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 200);
441
442 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
443 processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
444
445 std::list<NotifyArgs> args = processSync(conv);
446 ASSERT_EQ(2u, args.size());
447 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
448 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
449 WithCoords(52, 99), WithToolType(ToolType::FINGER)));
450 args.pop_front();
451 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
452 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
453 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
454 WithPointerCount(2u), WithPointerCoords(0, 52, 99),
455 WithPointerCoords(1, 250, 200), WithPointerToolType(0, ToolType::FINGER),
456 WithPointerToolType(1, ToolType::FINGER)));
457
458 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
459 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
460 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
461 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 255);
462 processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 202);
463
464 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
465 processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
466
467 args = processSync(conv);
468 ASSERT_EQ(2u, args.size());
469 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
470 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(2u),
471 WithPointerCoords(0, 52, 99), WithPointerCoords(1, 255, 202),
472 WithPointerToolType(1, ToolType::FINGER),
473 WithPointerToolType(0, ToolType::FINGER)));
474 args.pop_front();
475 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
476 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_UP |
477 0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
478 WithPointerCount(2u), WithPointerCoords(0, 52, 99),
479 WithPointerCoords(1, 255, 202), WithPointerToolType(0, ToolType::FINGER),
480 WithPointerToolType(1, ToolType::FINGER)));
481
482 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
483 processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
484 processAxis(conv, EV_KEY, BTN_TOUCH, 0);
485
486 args = processSync(conv);
487 ASSERT_EQ(2u, args.size());
488 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
489 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
490 WithCoords(255, 202), WithToolType(ToolType::FINGER)));
491 args.pop_front();
492 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
493 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithPointerCount(1u),
494 WithCoords(255, 202), WithToolType(ToolType::FINGER)));
495}
496
497// Pointer IDs max out at 31, and so must be reused once a touch is lifted to avoid running out.
498TEST_F(CapturedTouchpadEventConverterTest, PointerIdsReusedAfterLift) {
499 CapturedTouchpadEventConverter conv = createConverter();
500
501 // Put down two fingers, which should get IDs 0 and 1.
502 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
503 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
504 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 10);
505 processAxis(conv, EV_ABS, ABS_MT_SLOT, 1);
506 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
507 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 20);
508
509 processAxis(conv, EV_KEY, BTN_TOUCH, 1);
510 processAxis(conv, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
511
512 std::list<NotifyArgs> args = processSync(conv);
513 ASSERT_EQ(2u, args.size());
514 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
515 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
516 WithPointerId(/*index=*/0, /*id=*/0)));
517 args.pop_front();
518 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
519 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
520 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
521 WithPointerCount(2u), WithPointerId(/*index=*/0, /*id=*/0),
522 WithPointerId(/*index=*/1, /*id=*/1)));
523
524 // Lift the finger in slot 0, freeing up pointer ID 0...
525 processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
526 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
527
528 // ...and simultaneously add a finger in slot 2.
529 processAxis(conv, EV_ABS, ABS_MT_SLOT, 2);
530 processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 3);
531 processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 30);
532
533 args = processSync(conv);
534 ASSERT_EQ(3u, args.size());
535 // Slot 1 being present will result in a MOVE event, even though it hasn't actually moved (see
536 // comments in CapturedTouchpadEventConverter::sync).
537 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
538 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(2u),
539 WithPointerId(/*index=*/0, /*id=*/0), WithPointerId(/*index=*/1, /*id=*/1)));
540 args.pop_front();
541 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
542 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_UP |
543 0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
544 WithPointerCount(2u), WithPointerId(/*index=*/0, /*id=*/0),
545 WithPointerId(/*index=*/1, /*id=*/1)));
546 args.pop_front();
547 // Slot 0 being lifted causes the finger from slot 1 to move up to index 0, but keep its
548 // previous ID. The new finger in slot 2 should take ID 0, which was just freed up.
549 EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
550 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_POINTER_DOWN |
551 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
552 WithPointerCount(2u), WithPointerId(/*index=*/0, /*id=*/1),
553 WithPointerId(/*index=*/1, /*id=*/0)));
554}
555
556} // namespace android