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 23 namespace { 24 25 static 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 32 const char kTestDevicePath[] = "/dev/input/test-device"; 33 34 } // namespace 35 36 namespace ui { 37 38 class 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 virtual 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 72 MockTouchEventConverterEvdev::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 102 void 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. 116 class 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. 152 TEST_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 187 TEST_F(TouchEventConverterEvdevTest, NoEvents) { 188 ui::MockTouchEventConverterEvdev* dev = device(); 189 dev->ConfigureReadMock(NULL, 0, 0); 190 EXPECT_EQ(0u, dev->size()); 191 } 192 193 TEST_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 248 TEST_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 285 TEST_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 425 TEST_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 447 TEST_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