1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include <linux/input.h>
12 #include "base/bind.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "base/run_loop.h"
17 #include "base/time/time.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "ui/events/event.h"
20 #include "ui/events/ozone/evdev/touch_event_converter_evdev.h"
21 #include "ui/events/platform/platform_event_dispatcher.h"
22 #include "ui/events/platform/platform_event_source.h"
26 static int SetNonBlocking(int fd) {
27 int flags = fcntl(fd, F_GETFL, 0);
30 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
33 const char kTestDevicePath[] = "/dev/input/test-device";
39 class MockTouchEventConverterEvdev : public TouchEventConverterEvdev {
41 MockTouchEventConverterEvdev(int fd, base::FilePath path);
42 ~MockTouchEventConverterEvdev() override {}
44 void ConfigureReadMock(struct input_event* queue,
48 unsigned size() { return dispatched_events_.size(); }
49 TouchEvent* event(unsigned index) {
50 DCHECK_GT(dispatched_events_.size(), index);
51 Event* ev = dispatched_events_[index];
52 DCHECK(ev->IsTouchEvent());
53 return static_cast<TouchEvent*>(ev);
56 // Actually dispatch the event reader code.
58 OnFileCanReadWithoutBlocking(read_pipe_);
59 base::RunLoop().RunUntilIdle();
62 void DispatchCallback(scoped_ptr<Event> event) {
63 dispatched_events_.push_back(event.release());
66 bool Reinitialize() override { return true; }
72 ScopedVector<Event> dispatched_events_;
74 DISALLOW_COPY_AND_ASSIGN(MockTouchEventConverterEvdev);
77 MockTouchEventConverterEvdev::MockTouchEventConverterEvdev(int fd,
79 : TouchEventConverterEvdev(
84 base::Bind(&MockTouchEventConverterEvdev::DispatchCallback,
85 base::Unretained(this))) {
89 // TODO(rjkroege): Check test axes.
90 x_min_pixels_ = x_min_tuxels_ = 0;
91 x_num_pixels_ = x_num_tuxels_ = std::numeric_limits<int>::max();
92 y_min_pixels_ = y_min_tuxels_ = 0;
93 y_num_pixels_ = y_num_tuxels_ = std::numeric_limits<int>::max();
98 PLOG(FATAL) << "failed pipe";
100 DCHECK(SetNonBlocking(fds[0]) == 0)
101 << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
102 DCHECK(SetNonBlocking(fds[1]) == 0)
103 << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
105 write_pipe_ = fds[1];
108 void MockTouchEventConverterEvdev::ConfigureReadMock(struct input_event* queue,
111 int nwrite = HANDLE_EINTR(write(write_pipe_,
113 sizeof(struct input_event) * read_this_many));
115 static_cast<int>(sizeof(struct input_event) * read_this_many))
116 << "write() failed, errno: " << errno;
122 class TouchEventConverterEvdevTest : public testing::Test {
124 TouchEventConverterEvdevTest() {}
126 // Overridden from testing::Test:
127 void SetUp() override {
128 // Set up pipe to satisfy message pump (unused).
131 PLOG(FATAL) << "failed pipe";
132 events_in_ = evdev_io[0];
133 events_out_ = evdev_io[1];
135 loop_ = new base::MessageLoopForUI;
136 device_ = new ui::MockTouchEventConverterEvdev(
137 events_in_, base::FilePath(kTestDevicePath));
140 void TearDown() override {
145 ui::MockTouchEventConverterEvdev* device() { return device_; }
148 base::MessageLoop* loop_;
149 ui::MockTouchEventConverterEvdev* device_;
154 DISALLOW_COPY_AND_ASSIGN(TouchEventConverterEvdevTest);
157 // TODO(rjkroege): Test for valid handling of time stamps.
158 TEST_F(TouchEventConverterEvdevTest, TouchDown) {
159 ui::MockTouchEventConverterEvdev* dev = device();
161 struct input_event mock_kernel_queue[] = {
162 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
163 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
164 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
165 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
166 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
169 dev->ConfigureReadMock(mock_kernel_queue, 1, 0);
171 EXPECT_EQ(0u, dev->size());
173 dev->ConfigureReadMock(mock_kernel_queue, 2, 1);
175 EXPECT_EQ(0u, dev->size());
177 dev->ConfigureReadMock(mock_kernel_queue, 3, 3);
179 EXPECT_EQ(1u, dev->size());
181 ui::TouchEvent* event = dev->event(0);
182 EXPECT_FALSE(event == NULL);
184 EXPECT_EQ(ui::ET_TOUCH_PRESSED, event->type());
185 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
186 EXPECT_EQ(42, event->x());
187 EXPECT_EQ(51, event->y());
188 EXPECT_EQ(0, event->touch_id());
189 EXPECT_FLOAT_EQ(1.5f, event->radius_x());
190 EXPECT_FLOAT_EQ(.5f, event->force());
191 EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
194 TEST_F(TouchEventConverterEvdevTest, NoEvents) {
195 ui::MockTouchEventConverterEvdev* dev = device();
196 dev->ConfigureReadMock(NULL, 0, 0);
197 EXPECT_EQ(0u, dev->size());
200 TEST_F(TouchEventConverterEvdevTest, TouchMove) {
201 ui::MockTouchEventConverterEvdev* dev = device();
203 struct input_event mock_kernel_queue_press[] = {
204 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
205 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
206 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
207 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
208 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
211 struct input_event mock_kernel_queue_move1[] = {
212 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 50},
213 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
214 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 43}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
217 struct input_event mock_kernel_queue_move2[] = {
218 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 42}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
221 // Setup and discard a press.
222 dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0);
224 EXPECT_EQ(1u, dev->size());
226 dev->ConfigureReadMock(mock_kernel_queue_move1, 4, 0);
228 EXPECT_EQ(2u, dev->size());
229 ui::TouchEvent* event = dev->event(1);
230 EXPECT_FALSE(event == NULL);
232 EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type());
233 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
234 EXPECT_EQ(42, event->x());
235 EXPECT_EQ(43, event->y());
236 EXPECT_EQ(0, event->touch_id());
237 EXPECT_FLOAT_EQ(2.f / 3.f, event->force());
238 EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
240 dev->ConfigureReadMock(mock_kernel_queue_move2, 2, 0);
242 EXPECT_EQ(3u, dev->size());
243 event = dev->event(2);
244 EXPECT_FALSE(event == NULL);
246 EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type());
247 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
248 EXPECT_EQ(42, event->x());
249 EXPECT_EQ(42, event->y());
250 EXPECT_EQ(0, event->touch_id());
251 EXPECT_FLOAT_EQ(2.f / 3.f, event->force());
252 EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
255 TEST_F(TouchEventConverterEvdevTest, TouchRelease) {
256 ui::MockTouchEventConverterEvdev* dev = device();
258 struct input_event mock_kernel_queue_press[] = {
259 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
260 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
261 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
262 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
263 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
266 struct input_event mock_kernel_queue_release[] = {
267 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
270 // Setup and discard a press.
271 dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0);
273 EXPECT_EQ(1u, dev->size());
274 ui::TouchEvent* event = dev->event(0);
275 EXPECT_FALSE(event == NULL);
277 dev->ConfigureReadMock(mock_kernel_queue_release, 2, 0);
279 EXPECT_EQ(2u, dev->size());
280 event = dev->event(1);
281 EXPECT_FALSE(event == NULL);
283 EXPECT_EQ(ui::ET_TOUCH_RELEASED, event->type());
284 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
285 EXPECT_EQ(42, event->x());
286 EXPECT_EQ(51, event->y());
287 EXPECT_EQ(0, event->touch_id());
288 EXPECT_FLOAT_EQ(.5f, event->force());
289 EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
292 TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
293 ui::MockTouchEventConverterEvdev* dev = device();
298 struct input_event mock_kernel_queue_press0[] = {
299 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
300 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
301 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
302 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
303 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
305 // Setup and discard a press.
306 dev->ConfigureReadMock(mock_kernel_queue_press0, 6, 0);
308 EXPECT_EQ(1u, dev->size());
310 struct input_event mock_kernel_queue_move0[] = {
311 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
313 // Setup and discard a move.
314 dev->ConfigureReadMock(mock_kernel_queue_move0, 2, 0);
316 EXPECT_EQ(2u, dev->size());
318 struct input_event mock_kernel_queue_move0press1[] = {
319 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0},
320 {{0, 0}, EV_ABS, ABS_MT_SLOT, 1}, {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 686},
321 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
322 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
323 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 101},
324 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 102}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
326 // Move on 0, press on 1.
327 dev->ConfigureReadMock(mock_kernel_queue_move0press1, 9, 0);
329 EXPECT_EQ(4u, dev->size());
334 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type());
335 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
336 EXPECT_EQ(40, ev0->x());
337 EXPECT_EQ(51, ev0->y());
338 EXPECT_EQ(0, ev0->touch_id());
339 EXPECT_FLOAT_EQ(.5f, ev0->force());
340 EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
343 EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1->type());
344 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
345 EXPECT_EQ(101, ev1->x());
346 EXPECT_EQ(102, ev1->y());
347 EXPECT_EQ(1, ev1->touch_id());
348 EXPECT_FLOAT_EQ(.5f, ev1->force());
349 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
351 // Stationary 0, Moves 1.
352 struct input_event mock_kernel_queue_stationary0_move1[] = {
353 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
355 dev->ConfigureReadMock(mock_kernel_queue_stationary0_move1, 2, 0);
357 EXPECT_EQ(5u, dev->size());
360 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type());
361 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
362 EXPECT_EQ(40, ev1->x());
363 EXPECT_EQ(102, ev1->y());
364 EXPECT_EQ(1, ev1->touch_id());
366 EXPECT_FLOAT_EQ(.5f, ev1->force());
367 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
369 // Move 0, stationary 1.
370 struct input_event mock_kernel_queue_move0_stationary1[] = {
371 {{0, 0}, EV_ABS, ABS_MT_SLOT, 0}, {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 39},
372 {{0, 0}, EV_SYN, SYN_REPORT, 0}
374 dev->ConfigureReadMock(mock_kernel_queue_move0_stationary1, 3, 0);
376 EXPECT_EQ(6u, dev->size());
379 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type());
380 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
381 EXPECT_EQ(39, ev0->x());
382 EXPECT_EQ(51, ev0->y());
383 EXPECT_EQ(0, ev0->touch_id());
384 EXPECT_FLOAT_EQ(.5f, ev0->force());
385 EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
387 // Release 0, move 1.
388 struct input_event mock_kernel_queue_release0_move1[] = {
389 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_ABS, ABS_MT_SLOT, 1},
390 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 38}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
392 dev->ConfigureReadMock(mock_kernel_queue_release0_move1, 4, 0);
394 EXPECT_EQ(8u, dev->size());
398 EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0->type());
399 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
400 EXPECT_EQ(39, ev0->x());
401 EXPECT_EQ(51, ev0->y());
402 EXPECT_EQ(0, ev0->touch_id());
403 EXPECT_FLOAT_EQ(.5f, ev0->force());
404 EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
406 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type());
407 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
408 EXPECT_EQ(38, ev1->x());
409 EXPECT_EQ(102, ev1->y());
410 EXPECT_EQ(1, ev1->touch_id());
411 EXPECT_FLOAT_EQ(.5f, ev1->force());
412 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
415 struct input_event mock_kernel_queue_release1[] = {
416 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0},
418 dev->ConfigureReadMock(mock_kernel_queue_release1, 2, 0);
420 EXPECT_EQ(9u, dev->size());
423 EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1->type());
424 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
425 EXPECT_EQ(38, ev1->x());
426 EXPECT_EQ(102, ev1->y());
427 EXPECT_EQ(1, ev1->touch_id());
428 EXPECT_FLOAT_EQ(.5f, ev1->force());
429 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
432 TEST_F(TouchEventConverterEvdevTest, TypeA) {
433 ui::MockTouchEventConverterEvdev* dev = device();
435 struct input_event mock_kernel_queue_press0[] = {
436 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
437 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
438 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
439 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51},
440 {{0, 0}, EV_SYN, SYN_MT_REPORT, 0},
441 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
442 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 61},
443 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 71},
444 {{0, 0}, EV_SYN, SYN_MT_REPORT, 0},
445 {{0, 0}, EV_SYN, SYN_REPORT, 0}
448 // Check that two events are generated.
449 dev->ConfigureReadMock(mock_kernel_queue_press0, 10, 0);
451 EXPECT_EQ(2u, dev->size());
454 TEST_F(TouchEventConverterEvdevTest, Unsync) {
455 ui::MockTouchEventConverterEvdev* dev = device();
457 struct input_event mock_kernel_queue_press0[] = {
458 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
459 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
460 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
461 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
462 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
465 dev->ConfigureReadMock(mock_kernel_queue_press0, 6, 0);
467 EXPECT_EQ(1u, dev->size());
469 // Prepare a move with a drop.
470 struct input_event mock_kernel_queue_move0[] = {
471 {{0, 0}, EV_SYN, SYN_DROPPED, 0},
472 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
475 // Verify that we didn't receive it/
476 dev->ConfigureReadMock(mock_kernel_queue_move0, 3, 0);
478 EXPECT_EQ(1u, dev->size());
480 struct input_event mock_kernel_queue_move1[] = {
481 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
484 // Verify that it re-syncs after a SYN_REPORT.
485 dev->ConfigureReadMock(mock_kernel_queue_move1, 2, 0);
487 EXPECT_EQ(2u, dev->size());
491 TEST_F(TouchEventConverterEvdevTest,
492 DontChangeMultitouchPositionFromLegacyAxes) {
493 ui::MockTouchEventConverterEvdev* dev = device();
495 struct input_event mock_kernel_queue[] = {
496 {{0, 0}, EV_ABS, ABS_MT_SLOT, 0},
497 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 100},
498 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 999},
499 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 888},
500 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 55},
501 {{0, 0}, EV_ABS, ABS_MT_SLOT, 1},
502 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 200},
503 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 44},
504 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 777},
505 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 666},
506 {{0, 0}, EV_ABS, ABS_X, 999},
507 {{0, 0}, EV_ABS, ABS_Y, 888},
508 {{0, 0}, EV_ABS, ABS_PRESSURE, 55},
509 {{0, 0}, EV_SYN, SYN_REPORT, 0},
512 // Check that two events are generated.
513 dev->ConfigureReadMock(mock_kernel_queue, arraysize(mock_kernel_queue), 0);
516 const unsigned int kExpectedEventCount = 2;
517 EXPECT_EQ(kExpectedEventCount, dev->size());
518 if (kExpectedEventCount != dev->size())
521 ui::TouchEvent* ev0 = dev->event(0);
522 ui::TouchEvent* ev1 = dev->event(1);
524 EXPECT_EQ(0, ev0->touch_id());
525 EXPECT_EQ(999, ev0->x());
526 EXPECT_EQ(888, ev0->y());
527 EXPECT_FLOAT_EQ(0.8333333f, ev0->force());
529 EXPECT_EQ(1, ev1->touch_id());
530 EXPECT_EQ(777, ev1->x());
531 EXPECT_EQ(666, ev1->y());
532 EXPECT_FLOAT_EQ(0.4666666f, ev1->force());