touch_event_converter_evdev_unittest.cc revision 0de6073388f4e2780db8536178b129cd8f6ab386
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.
4
5#include <errno.h>
6#include <fcntl.h>
7#include <linux/input.h>
8#include <unistd.h>
9
10#include <vector>
11
12#include "base/memory/scoped_ptr.h"
13#include "base/memory/scoped_vector.h"
14#include "base/posix/eintr_wrapper.h"
15#include "base/run_loop.h"
16#include "base/time/time.h"
17#include "testing/gtest/include/gtest/gtest.h"
18#include "ui/events/event.h"
19#include "ui/events/ozone/evdev/touch_event_converter_evdev.h"
20#include "ui/events/platform/platform_event_dispatcher.h"
21#include "ui/events/platform/platform_event_source.h"
22
23namespace {
24
25static int SetNonBlocking(int fd) {
26  int flags = fcntl(fd, F_GETFL, 0);
27  if (flags == -1)
28    flags = 0;
29  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
30}
31
32const char kTestDevicePath[] = "/dev/input/test-device";
33
34}  // namespace
35
36namespace ui {
37
38class MockTouchEventConverterEvdev : public TouchEventConverterEvdev {
39 public:
40  MockTouchEventConverterEvdev(int fd, base::FilePath path);
41  virtual ~MockTouchEventConverterEvdev() {};
42
43  void ConfigureReadMock(struct input_event* queue,
44                         long read_this_many,
45                         long queue_index);
46
47  unsigned size() { return dispatched_events_.size(); }
48  TouchEvent* event(unsigned index) { return dispatched_events_[index]; }
49
50  // Actually dispatch the event reader code.
51  void ReadNow() {
52    OnFileCanReadWithoutBlocking(read_pipe_);
53    base::RunLoop().RunUntilIdle();
54  }
55
56  void DispatchCallback(Event* event) {
57    dispatched_events_.push_back(
58        new TouchEvent(*static_cast<TouchEvent*>(event)));
59  }
60
61  bool Reinitialize() OVERRIDE { return true; }
62
63 private:
64  int read_pipe_;
65  int write_pipe_;
66
67  ScopedVector<TouchEvent> dispatched_events_;
68
69  DISALLOW_COPY_AND_ASSIGN(MockTouchEventConverterEvdev);
70};
71
72MockTouchEventConverterEvdev::MockTouchEventConverterEvdev(int fd,
73                                                           base::FilePath path)
74    : TouchEventConverterEvdev(
75          fd,
76          path,
77          EventDeviceInfo(),
78          base::Bind(&MockTouchEventConverterEvdev::DispatchCallback,
79                     base::Unretained(this))) {
80  pressure_min_ = 30;
81  pressure_max_ = 60;
82
83  // TODO(rjkroege): Check test axes.
84  x_min_pixels_ = x_min_tuxels_ = 0;
85  x_num_pixels_ = x_num_tuxels_ = std::numeric_limits<int>::max();
86  y_min_pixels_ = y_min_tuxels_ = 0;
87  y_num_pixels_ = y_num_tuxels_ = std::numeric_limits<int>::max();
88
89  int fds[2];
90
91  if (pipe(fds))
92    PLOG(FATAL) << "failed pipe";
93
94  DCHECK(SetNonBlocking(fds[0]) == 0)
95      << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
96  DCHECK(SetNonBlocking(fds[1]) == 0)
97      << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
98  read_pipe_ = fds[0];
99  write_pipe_ = fds[1];
100}
101
102void MockTouchEventConverterEvdev::ConfigureReadMock(struct input_event* queue,
103                                                     long read_this_many,
104                                                     long queue_index) {
105  int nwrite = HANDLE_EINTR(write(write_pipe_,
106                                  queue + queue_index,
107                                  sizeof(struct input_event) * read_this_many));
108  DCHECK(nwrite ==
109         static_cast<int>(sizeof(struct input_event) * read_this_many))
110      << "write() failed, errno: " << errno;
111}
112
113}  // namespace ui
114
115// Test fixture.
116class TouchEventConverterEvdevTest : public testing::Test {
117 public:
118  TouchEventConverterEvdevTest() {}
119
120  // Overridden from testing::Test:
121  virtual void SetUp() OVERRIDE {
122    // Set up pipe to satisfy message pump (unused).
123    int evdev_io[2];
124    if (pipe(evdev_io))
125      PLOG(FATAL) << "failed pipe";
126    events_in_ = evdev_io[0];
127    events_out_ = evdev_io[1];
128
129    loop_ = new base::MessageLoopForUI;
130    device_ = new ui::MockTouchEventConverterEvdev(
131        events_in_, base::FilePath(kTestDevicePath));
132  }
133
134  virtual void TearDown() OVERRIDE {
135    delete device_;
136    delete loop_;
137  }
138
139  ui::MockTouchEventConverterEvdev* device() { return device_; }
140
141 private:
142  base::MessageLoop* loop_;
143  ui::MockTouchEventConverterEvdev* device_;
144
145  int events_out_;
146  int events_in_;
147
148  DISALLOW_COPY_AND_ASSIGN(TouchEventConverterEvdevTest);
149};
150
151// TODO(rjkroege): Test for valid handling of time stamps.
152TEST_F(TouchEventConverterEvdevTest, TouchDown) {
153  ui::MockTouchEventConverterEvdev* dev = device();
154
155  struct input_event mock_kernel_queue[] = {
156    {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
157    {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
158    {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
159    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
160    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
161  };
162
163  dev->ConfigureReadMock(mock_kernel_queue, 1, 0);
164  dev->ReadNow();
165  EXPECT_EQ(0u, dev->size());
166
167  dev->ConfigureReadMock(mock_kernel_queue, 2, 1);
168  dev->ReadNow();
169  EXPECT_EQ(0u, dev->size());
170
171  dev->ConfigureReadMock(mock_kernel_queue, 3, 3);
172  dev->ReadNow();
173  EXPECT_EQ(1u, dev->size());
174
175  ui::TouchEvent* event = dev->event(0);
176  EXPECT_FALSE(event == NULL);
177
178  EXPECT_EQ(ui::ET_TOUCH_PRESSED, event->type());
179  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
180  EXPECT_EQ(42, event->x());
181  EXPECT_EQ(51, event->y());
182  EXPECT_EQ(0, event->touch_id());
183  EXPECT_FLOAT_EQ(.5f, event->force());
184  EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
185}
186
187TEST_F(TouchEventConverterEvdevTest, NoEvents) {
188  ui::MockTouchEventConverterEvdev* dev = device();
189  dev->ConfigureReadMock(NULL, 0, 0);
190  EXPECT_EQ(0u, dev->size());
191}
192
193TEST_F(TouchEventConverterEvdevTest, TouchMove) {
194  ui::MockTouchEventConverterEvdev* dev = device();
195
196  struct input_event mock_kernel_queue_press[] = {
197    {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
198    {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
199    {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
200    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
201    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
202  };
203
204  struct input_event mock_kernel_queue_move1[] = {
205    {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 50},
206    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
207    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 43}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
208  };
209
210  struct input_event mock_kernel_queue_move2[] = {
211    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 42}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
212  };
213
214  // Setup and discard a press.
215  dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0);
216  dev->ReadNow();
217  EXPECT_EQ(1u, dev->size());
218
219  dev->ConfigureReadMock(mock_kernel_queue_move1, 4, 0);
220  dev->ReadNow();
221  EXPECT_EQ(2u, dev->size());
222  ui::TouchEvent* event = dev->event(1);
223  EXPECT_FALSE(event == NULL);
224
225  EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type());
226  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
227  EXPECT_EQ(42, event->x());
228  EXPECT_EQ(43, event->y());
229  EXPECT_EQ(0, event->touch_id());
230  EXPECT_FLOAT_EQ(2.f / 3.f, event->force());
231  EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
232
233  dev->ConfigureReadMock(mock_kernel_queue_move2, 2, 0);
234  dev->ReadNow();
235  EXPECT_EQ(3u, dev->size());
236  event = dev->event(2);
237  EXPECT_FALSE(event == NULL);
238
239  EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type());
240  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
241  EXPECT_EQ(42, event->x());
242  EXPECT_EQ(42, event->y());
243  EXPECT_EQ(0, event->touch_id());
244  EXPECT_FLOAT_EQ(2.f / 3.f, event->force());
245  EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
246}
247
248TEST_F(TouchEventConverterEvdevTest, TouchRelease) {
249  ui::MockTouchEventConverterEvdev* dev = device();
250
251  struct input_event mock_kernel_queue_press[] = {
252    {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
253    {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
254    {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
255    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
256    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
257  };
258
259  struct input_event mock_kernel_queue_release[] = {
260    {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
261  };
262
263  // Setup and discard a press.
264  dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0);
265  dev->ReadNow();
266  EXPECT_EQ(1u, dev->size());
267  ui::TouchEvent* event = dev->event(0);
268  EXPECT_FALSE(event == NULL);
269
270  dev->ConfigureReadMock(mock_kernel_queue_release, 2, 0);
271  dev->ReadNow();
272  EXPECT_EQ(2u, dev->size());
273  event = dev->event(1);
274  EXPECT_FALSE(event == NULL);
275
276  EXPECT_EQ(ui::ET_TOUCH_RELEASED, event->type());
277  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
278  EXPECT_EQ(42, event->x());
279  EXPECT_EQ(51, event->y());
280  EXPECT_EQ(0, event->touch_id());
281  EXPECT_FLOAT_EQ(.5f, event->force());
282  EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
283}
284
285TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
286  ui::MockTouchEventConverterEvdev* dev = device();
287
288  ui::TouchEvent* ev0;
289  ui::TouchEvent* ev1;
290
291  struct input_event mock_kernel_queue_press0[] = {
292    {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
293    {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
294    {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
295    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
296    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
297  };
298  // Setup and discard a press.
299  dev->ConfigureReadMock(mock_kernel_queue_press0, 6, 0);
300  dev->ReadNow();
301  EXPECT_EQ(1u, dev->size());
302
303  struct input_event mock_kernel_queue_move0[] = {
304    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
305  };
306  // Setup and discard a move.
307  dev->ConfigureReadMock(mock_kernel_queue_move0, 2, 0);
308  dev->ReadNow();
309  EXPECT_EQ(2u, dev->size());
310
311  struct input_event mock_kernel_queue_move0press1[] = {
312    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0},
313    {{0, 0}, EV_ABS, ABS_MT_SLOT, 1}, {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 686},
314    {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
315    {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
316    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 101},
317    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 102}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
318  };
319  // Move on 0, press on 1.
320  dev->ConfigureReadMock(mock_kernel_queue_move0press1, 9, 0);
321  dev->ReadNow();
322  EXPECT_EQ(4u, dev->size());
323  ev0 = dev->event(2);
324  ev1 = dev->event(3);
325
326  // Move
327  EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type());
328  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
329  EXPECT_EQ(40, ev0->x());
330  EXPECT_EQ(51, ev0->y());
331  EXPECT_EQ(0, ev0->touch_id());
332  EXPECT_FLOAT_EQ(.5f, ev0->force());
333  EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
334
335  // Press
336  EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1->type());
337  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
338  EXPECT_EQ(101, ev1->x());
339  EXPECT_EQ(102, ev1->y());
340  EXPECT_EQ(1, ev1->touch_id());
341  EXPECT_FLOAT_EQ(.5f, ev1->force());
342  EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
343
344  // Stationary 0, Moves 1.
345  struct input_event mock_kernel_queue_stationary0_move1[] = {
346    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
347  };
348  dev->ConfigureReadMock(mock_kernel_queue_stationary0_move1, 2, 0);
349  dev->ReadNow();
350  EXPECT_EQ(5u, dev->size());
351  ev1 = dev->event(4);
352
353  EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type());
354  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
355  EXPECT_EQ(40, ev1->x());
356  EXPECT_EQ(102, ev1->y());
357  EXPECT_EQ(1, ev1->touch_id());
358
359  EXPECT_FLOAT_EQ(.5f, ev1->force());
360  EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
361
362  // Move 0, stationary 1.
363  struct input_event mock_kernel_queue_move0_stationary1[] = {
364    {{0, 0}, EV_ABS, ABS_MT_SLOT, 0}, {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 39},
365    {{0, 0}, EV_SYN, SYN_REPORT, 0}
366  };
367  dev->ConfigureReadMock(mock_kernel_queue_move0_stationary1, 3, 0);
368  dev->ReadNow();
369  EXPECT_EQ(6u, dev->size());
370  ev0 = dev->event(5);
371
372  EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type());
373  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
374  EXPECT_EQ(39, ev0->x());
375  EXPECT_EQ(51, ev0->y());
376  EXPECT_EQ(0, ev0->touch_id());
377  EXPECT_FLOAT_EQ(.5f, ev0->force());
378  EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
379
380  // Release 0, move 1.
381  struct input_event mock_kernel_queue_release0_move1[] = {
382    {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_ABS, ABS_MT_SLOT, 1},
383    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 38}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
384  };
385  dev->ConfigureReadMock(mock_kernel_queue_release0_move1, 4, 0);
386  dev->ReadNow();
387  EXPECT_EQ(8u, dev->size());
388  ev0 = dev->event(6);
389  ev1 = dev->event(7);
390
391  EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0->type());
392  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
393  EXPECT_EQ(39, ev0->x());
394  EXPECT_EQ(51, ev0->y());
395  EXPECT_EQ(0, ev0->touch_id());
396  EXPECT_FLOAT_EQ(.5f, ev0->force());
397  EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
398
399  EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type());
400  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
401  EXPECT_EQ(38, ev1->x());
402  EXPECT_EQ(102, ev1->y());
403  EXPECT_EQ(1, ev1->touch_id());
404  EXPECT_FLOAT_EQ(.5f, ev1->force());
405  EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
406
407  // Release 1.
408  struct input_event mock_kernel_queue_release1[] = {
409    {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0},
410  };
411  dev->ConfigureReadMock(mock_kernel_queue_release1, 2, 0);
412  dev->ReadNow();
413  EXPECT_EQ(9u, dev->size());
414  ev1 = dev->event(8);
415
416  EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1->type());
417  EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
418  EXPECT_EQ(38, ev1->x());
419  EXPECT_EQ(102, ev1->y());
420  EXPECT_EQ(1, ev1->touch_id());
421  EXPECT_FLOAT_EQ(.5f, ev1->force());
422  EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
423}
424
425TEST_F(TouchEventConverterEvdevTest, TypeA) {
426  ui::MockTouchEventConverterEvdev* dev = device();
427
428  struct input_event mock_kernel_queue_press0[] = {
429    {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
430    {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
431    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
432    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51},
433    {{0, 0}, EV_SYN, SYN_MT_REPORT, 0},
434    {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
435    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 61},
436    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 71},
437    {{0, 0}, EV_SYN, SYN_MT_REPORT, 0},
438    {{0, 0}, EV_SYN, SYN_REPORT, 0}
439  };
440
441  // Check that two events are generated.
442  dev->ConfigureReadMock(mock_kernel_queue_press0, 10, 0);
443  dev->ReadNow();
444  EXPECT_EQ(2u, dev->size());
445}
446
447TEST_F(TouchEventConverterEvdevTest, Unsync) {
448  ui::MockTouchEventConverterEvdev* dev = device();
449
450  struct input_event mock_kernel_queue_press0[] = {
451    {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
452    {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
453    {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
454    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
455    {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
456  };
457
458  dev->ConfigureReadMock(mock_kernel_queue_press0, 6, 0);
459  dev->ReadNow();
460  EXPECT_EQ(1u, dev->size());
461
462  // Prepare a move with a drop.
463  struct input_event mock_kernel_queue_move0[] = {
464    {{0, 0}, EV_SYN, SYN_DROPPED, 0},
465    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
466  };
467
468  // Verify that we didn't receive it/
469  dev->ConfigureReadMock(mock_kernel_queue_move0, 3, 0);
470  dev->ReadNow();
471  EXPECT_EQ(1u, dev->size());
472
473  struct input_event mock_kernel_queue_move1[] = {
474    {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
475  };
476
477  // Verify that it re-syncs after a SYN_REPORT.
478  dev->ConfigureReadMock(mock_kernel_queue_move1, 2, 0);
479  dev->ReadNow();
480  EXPECT_EQ(2u, dev->size());
481}
482