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/memory/scoped_ptr.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/message_loop/message_pump_dispatcher.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"
24 static int SetNonBlocking(int fd) {
25 int flags = fcntl(fd, F_GETFL, 0);
28 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
31 const char kTestDevicePath[] = "/dev/input/test-device";
37 class MockTouchEventConverterEvdev : public TouchEventConverterEvdev,
38 public base::MessagePumpDispatcher {
40 MockTouchEventConverterEvdev(int fd, base::FilePath path);
41 virtual ~MockTouchEventConverterEvdev() {};
43 void ConfigureReadMock(struct input_event* queue,
47 unsigned size() { return dispatched_events_.size(); }
48 TouchEvent* event(unsigned index) { return dispatched_events_[index]; }
50 // Actually dispatch the event reader code.
52 OnFileCanReadWithoutBlocking(read_pipe_);
53 base::RunLoop().RunUntilIdle();
56 virtual uint32_t Dispatch(const base::NativeEvent& event) OVERRIDE;
62 ScopedVector<TouchEvent> dispatched_events_;
64 DISALLOW_COPY_AND_ASSIGN(MockTouchEventConverterEvdev);
67 MockTouchEventConverterEvdev::MockTouchEventConverterEvdev(int fd,
69 : TouchEventConverterEvdev(fd, path, EventDeviceInfo()) {
73 // TODO(rjkroege): Check test axes.
75 x_max_ = std::numeric_limits<int>::max();
77 y_max_ = std::numeric_limits<int>::max();
82 NOTREACHED() << "failed pipe(): " << strerror(errno);
84 DCHECK(SetNonBlocking(fds[0]) == 0)
85 << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
86 DCHECK(SetNonBlocking(fds[1]) == 0)
87 << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
92 uint32_t MockTouchEventConverterEvdev::Dispatch(
93 const base::NativeEvent& event) {
94 ui::TouchEvent* ev = new ui::TouchEvent(event);
95 dispatched_events_.push_back(ev);
96 return POST_DISPATCH_NONE;
99 void MockTouchEventConverterEvdev::ConfigureReadMock(struct input_event* queue,
102 int nwrite = HANDLE_EINTR(write(write_pipe_,
104 sizeof(struct input_event) * read_this_many));
106 static_cast<int>(sizeof(struct input_event) * read_this_many))
107 << "write() failed, errno: " << errno;
113 class TouchEventConverterEvdevTest : public testing::Test {
115 TouchEventConverterEvdevTest() {}
117 // Overridden from testing::Test:
118 virtual void SetUp() OVERRIDE {
119 // Set up pipe to satisfy message pump (unused).
122 PLOG(FATAL) << "failed pipe";
123 events_in_ = evdev_io[0];
124 events_out_ = evdev_io[1];
126 loop_ = new base::MessageLoopForUI;
127 device_ = new ui::MockTouchEventConverterEvdev(
128 events_in_, base::FilePath(kTestDevicePath));
129 base::MessagePumpOzone::Current()->AddDispatcherForRootWindow(device_);
131 virtual void TearDown() OVERRIDE {
136 ui::MockTouchEventConverterEvdev* device() { return device_; }
139 base::MessageLoop* loop_;
140 ui::MockTouchEventConverterEvdev* device_;
145 DISALLOW_COPY_AND_ASSIGN(TouchEventConverterEvdevTest);
148 // TODO(rjkroege): Test for valid handling of time stamps.
149 TEST_F(TouchEventConverterEvdevTest, TouchDown) {
150 ui::MockTouchEventConverterEvdev* dev = device();
152 struct input_event mock_kernel_queue[] = {
153 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
154 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
155 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
156 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
157 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
160 dev->ConfigureReadMock(mock_kernel_queue, 1, 0);
162 EXPECT_EQ(0u, dev->size());
164 dev->ConfigureReadMock(mock_kernel_queue, 2, 1);
166 EXPECT_EQ(0u, dev->size());
168 dev->ConfigureReadMock(mock_kernel_queue, 3, 3);
170 EXPECT_EQ(1u, dev->size());
172 ui::TouchEvent* event = dev->event(0);
173 EXPECT_FALSE(event == NULL);
175 EXPECT_EQ(ui::ET_TOUCH_PRESSED, event->type());
176 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
177 EXPECT_EQ(42, event->x());
178 EXPECT_EQ(51, event->y());
179 EXPECT_EQ(0, event->touch_id());
180 EXPECT_FLOAT_EQ(.5f, event->force());
181 EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
184 TEST_F(TouchEventConverterEvdevTest, NoEvents) {
185 ui::MockTouchEventConverterEvdev* dev = device();
186 dev->ConfigureReadMock(NULL, 0, 0);
187 EXPECT_EQ(0u, dev->size());
190 TEST_F(TouchEventConverterEvdevTest, TouchMove) {
191 ui::MockTouchEventConverterEvdev* dev = device();
193 struct input_event mock_kernel_queue_press[] = {
194 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
195 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
196 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
197 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
198 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
201 struct input_event mock_kernel_queue_move1[] = {
202 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 50},
203 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
204 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 43}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
207 struct input_event mock_kernel_queue_move2[] = {
208 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 42}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
211 // Setup and discard a press.
212 dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0);
214 EXPECT_EQ(1u, dev->size());
216 dev->ConfigureReadMock(mock_kernel_queue_move1, 4, 0);
218 EXPECT_EQ(2u, dev->size());
219 ui::TouchEvent* event = dev->event(1);
220 EXPECT_FALSE(event == NULL);
222 EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type());
223 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
224 EXPECT_EQ(42, event->x());
225 EXPECT_EQ(43, event->y());
226 EXPECT_EQ(0, event->touch_id());
227 EXPECT_FLOAT_EQ(2.f / 3.f, event->force());
228 EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
230 dev->ConfigureReadMock(mock_kernel_queue_move2, 2, 0);
232 EXPECT_EQ(3u, dev->size());
233 event = dev->event(2);
234 EXPECT_FALSE(event == NULL);
236 EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type());
237 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
238 EXPECT_EQ(42, event->x());
239 EXPECT_EQ(42, event->y());
240 EXPECT_EQ(0, event->touch_id());
241 EXPECT_FLOAT_EQ(2.f / 3.f, event->force());
242 EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
245 TEST_F(TouchEventConverterEvdevTest, TouchRelease) {
246 ui::MockTouchEventConverterEvdev* dev = device();
248 struct input_event mock_kernel_queue_press[] = {
249 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
250 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
251 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
252 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
253 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
256 struct input_event mock_kernel_queue_release[] = {
257 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
260 // Setup and discard a press.
261 dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0);
263 EXPECT_EQ(1u, dev->size());
264 ui::TouchEvent* event = dev->event(0);
265 EXPECT_FALSE(event == NULL);
267 dev->ConfigureReadMock(mock_kernel_queue_release, 2, 0);
269 EXPECT_EQ(2u, dev->size());
270 event = dev->event(1);
271 EXPECT_FALSE(event == NULL);
273 EXPECT_EQ(ui::ET_TOUCH_RELEASED, event->type());
274 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
275 EXPECT_EQ(42, event->x());
276 EXPECT_EQ(51, event->y());
277 EXPECT_EQ(0, event->touch_id());
278 EXPECT_FLOAT_EQ(.5f, event->force());
279 EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
282 TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
283 ui::MockTouchEventConverterEvdev* dev = device();
288 struct input_event mock_kernel_queue_press0[] = {
289 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
290 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
291 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
292 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
293 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
295 // Setup and discard a press.
296 dev->ConfigureReadMock(mock_kernel_queue_press0, 6, 0);
298 EXPECT_EQ(1u, dev->size());
300 struct input_event mock_kernel_queue_move0[] = {
301 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
303 // Setup and discard a move.
304 dev->ConfigureReadMock(mock_kernel_queue_move0, 2, 0);
306 EXPECT_EQ(2u, dev->size());
308 struct input_event mock_kernel_queue_move0press1[] = {
309 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0},
310 {{0, 0}, EV_ABS, ABS_MT_SLOT, 1}, {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 686},
311 {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
312 {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
313 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 101},
314 {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 102}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
316 // Move on 0, press on 1.
317 dev->ConfigureReadMock(mock_kernel_queue_move0press1, 9, 0);
319 EXPECT_EQ(4u, dev->size());
324 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type());
325 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
326 EXPECT_EQ(40, ev0->x());
327 EXPECT_EQ(51, ev0->y());
328 EXPECT_EQ(0, ev0->touch_id());
329 EXPECT_FLOAT_EQ(.5f, ev0->force());
330 EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
333 EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1->type());
334 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
335 EXPECT_EQ(101, ev1->x());
336 EXPECT_EQ(102, ev1->y());
337 EXPECT_EQ(1, ev1->touch_id());
338 EXPECT_FLOAT_EQ(.5f, ev1->force());
339 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
341 // Stationary 0, Moves 1.
342 struct input_event mock_kernel_queue_stationary0_move1[] = {
343 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
345 dev->ConfigureReadMock(mock_kernel_queue_stationary0_move1, 2, 0);
347 EXPECT_EQ(5u, dev->size());
350 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type());
351 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
352 EXPECT_EQ(40, ev1->x());
353 EXPECT_EQ(102, ev1->y());
354 EXPECT_EQ(1, ev1->touch_id());
356 EXPECT_FLOAT_EQ(.5f, ev1->force());
357 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
359 // Move 0, stationary 1.
360 struct input_event mock_kernel_queue_move0_stationary1[] = {
361 {{0, 0}, EV_ABS, ABS_MT_SLOT, 0}, {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 39},
362 {{0, 0}, EV_SYN, SYN_REPORT, 0}
364 dev->ConfigureReadMock(mock_kernel_queue_move0_stationary1, 3, 0);
366 EXPECT_EQ(6u, dev->size());
369 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type());
370 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
371 EXPECT_EQ(39, ev0->x());
372 EXPECT_EQ(51, ev0->y());
373 EXPECT_EQ(0, ev0->touch_id());
374 EXPECT_FLOAT_EQ(.5f, ev0->force());
375 EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
377 // Release 0, move 1.
378 struct input_event mock_kernel_queue_release0_move1[] = {
379 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_ABS, ABS_MT_SLOT, 1},
380 {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 38}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
382 dev->ConfigureReadMock(mock_kernel_queue_release0_move1, 4, 0);
384 EXPECT_EQ(8u, dev->size());
388 EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0->type());
389 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
390 EXPECT_EQ(39, ev0->x());
391 EXPECT_EQ(51, ev0->y());
392 EXPECT_EQ(0, ev0->touch_id());
393 EXPECT_FLOAT_EQ(.5f, ev0->force());
394 EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
396 EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type());
397 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
398 EXPECT_EQ(38, ev1->x());
399 EXPECT_EQ(102, ev1->y());
400 EXPECT_EQ(1, ev1->touch_id());
401 EXPECT_FLOAT_EQ(.5f, ev1->force());
402 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
405 struct input_event mock_kernel_queue_release1[] = {
406 {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0},
408 dev->ConfigureReadMock(mock_kernel_queue_release1, 2, 0);
410 EXPECT_EQ(9u, dev->size());
413 EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1->type());
414 EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
415 EXPECT_EQ(38, ev1->x());
416 EXPECT_EQ(102, ev1->y());
417 EXPECT_EQ(1, ev1->touch_id());
418 EXPECT_FLOAT_EQ(.5f, ev1->force());
419 EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());