Home | History | Annotate | Download | only in evdev
      1 // Copyright (c) 2013 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/message_loop/message_loop.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/base/events/event.h"
     20 #include "ui/base/ozone/evdev/touch_event_converter_ozone.h"
     21 
     22 namespace {
     23 
     24 static int SetNonBlocking(int fd) {
     25   int flags = fcntl(fd, F_GETFL, 0);
     26   if (flags == -1)
     27     flags = 0;
     28   return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
     29 }
     30 
     31 }  // namespace
     32 
     33 namespace ui {
     34 
     35 class MockTouchEventConverterOzone : public TouchEventConverterOzone,
     36                                      public base::MessageLoop::Dispatcher {
     37  public:
     38   MockTouchEventConverterOzone(int a, int b);
     39   virtual ~MockTouchEventConverterOzone() {};
     40 
     41   void ConfigureReadMock(struct input_event* queue,
     42                          long read_this_many,
     43                          long queue_index);
     44 
     45   unsigned size() { return dispatched_events_.size(); }
     46   TouchEvent* event(unsigned index) { return dispatched_events_[index]; }
     47 
     48   // Actually dispatch the event reader code.
     49   void ReadNow() {
     50     OnFileCanReadWithoutBlocking(read_pipe_);
     51     base::RunLoop().RunUntilIdle();
     52   }
     53 
     54   virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
     55 
     56  private:
     57   int read_pipe_;
     58   int write_pipe_;
     59 
     60   ScopedVector<TouchEvent> dispatched_events_;
     61 
     62   DISALLOW_COPY_AND_ASSIGN(MockTouchEventConverterOzone);
     63 };
     64 
     65 MockTouchEventConverterOzone::MockTouchEventConverterOzone(int a, int b)
     66     : TouchEventConverterOzone(a, b) {
     67   pressure_min_ = 30;
     68   pressure_max_ = 60;
     69 
     70   int fds[2];
     71 
     72   DCHECK(pipe(fds) >= 0) << "pipe() failed, errno: " << errno;
     73   DCHECK(SetNonBlocking(fds[0]) == 0)
     74       << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
     75   DCHECK(SetNonBlocking(fds[1]) == 0)
     76       << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
     77   read_pipe_ = fds[0];
     78   write_pipe_ = fds[1];
     79 }
     80 
     81 bool MockTouchEventConverterOzone::Dispatch(const base::NativeEvent& event) {
     82   ui::TouchEvent* ev = new ui::TouchEvent(event);
     83   dispatched_events_.push_back(ev);
     84   return true;
     85 }
     86 
     87 void MockTouchEventConverterOzone::ConfigureReadMock(struct input_event* queue,
     88                                                      long read_this_many,
     89                                                      long queue_index) {
     90   int nwrite = HANDLE_EINTR(write(write_pipe_,
     91                                   queue + queue_index,
     92                                   sizeof(struct input_event) * read_this_many));
     93   DCHECK(nwrite ==
     94          static_cast<int>(sizeof(struct input_event) * read_this_many))
     95       << "write() failed, errno: " << errno;
     96 }
     97 
     98 }  // namespace ui
     99 
    100 // Test fixture.
    101 class TouchEventConverterOzoneTest : public testing::Test {
    102  public:
    103   TouchEventConverterOzoneTest() {}
    104 
    105   // Overridden from testing::Test:
    106   virtual void SetUp() OVERRIDE {
    107     loop_ = new base::MessageLoop(base::MessageLoop::TYPE_UI);
    108     device_ = new ui::MockTouchEventConverterOzone(-1, 2);
    109     base::MessagePumpOzone::Current()->AddDispatcherForRootWindow(device_);
    110   }
    111   virtual void TearDown() OVERRIDE {
    112     delete device_;
    113     delete loop_;
    114   }
    115 
    116   ui::MockTouchEventConverterOzone* device() { return device_; }
    117 
    118  private:
    119   base::MessageLoop* loop_;
    120   ui::MockTouchEventConverterOzone* device_;
    121   DISALLOW_COPY_AND_ASSIGN(TouchEventConverterOzoneTest);
    122 };
    123 
    124 // TODO(rjkroege): Test for valid handling of time stamps.
    125 TEST_F(TouchEventConverterOzoneTest, TouchDown) {
    126   ui::MockTouchEventConverterOzone* dev = device();
    127 
    128   struct input_event mock_kernel_queue[] = {
    129     {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
    130     {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
    131     {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
    132     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
    133     {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    134   };
    135 
    136   dev->ConfigureReadMock(mock_kernel_queue, 1, 0);
    137   dev->ReadNow();
    138   EXPECT_EQ(0u, dev->size());
    139 
    140   dev->ConfigureReadMock(mock_kernel_queue, 2, 1);
    141   dev->ReadNow();
    142   EXPECT_EQ(0u, dev->size());
    143 
    144   dev->ConfigureReadMock(mock_kernel_queue, 3, 3);
    145   dev->ReadNow();
    146   EXPECT_EQ(1u, dev->size());
    147 
    148   ui::TouchEvent* event = dev->event(0);
    149   EXPECT_FALSE(event == NULL);
    150 
    151   EXPECT_EQ(ui::ET_TOUCH_PRESSED, event->type());
    152   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
    153   EXPECT_EQ(42, event->x());
    154   EXPECT_EQ(51, event->y());
    155   EXPECT_EQ(0, event->touch_id());
    156   EXPECT_FLOAT_EQ(.5f, event->force());
    157   EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
    158 }
    159 
    160 TEST_F(TouchEventConverterOzoneTest, NoEvents) {
    161   ui::MockTouchEventConverterOzone* dev = device();
    162   dev->ConfigureReadMock(NULL, 0, 0);
    163   EXPECT_EQ(0u, dev->size());
    164 }
    165 
    166 TEST_F(TouchEventConverterOzoneTest, TouchMove) {
    167   ui::MockTouchEventConverterOzone* dev = device();
    168 
    169   struct input_event mock_kernel_queue_press[] = {
    170     {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
    171     {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
    172     {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
    173     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
    174     {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    175   };
    176 
    177   struct input_event mock_kernel_queue_move1[] = {
    178     {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 50},
    179     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
    180     {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 43}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    181   };
    182 
    183   struct input_event mock_kernel_queue_move2[] = {
    184     {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 42}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    185   };
    186 
    187   // Setup and discard a press.
    188   dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0);
    189   dev->ReadNow();
    190   EXPECT_EQ(1u, dev->size());
    191 
    192   dev->ConfigureReadMock(mock_kernel_queue_move1, 4, 0);
    193   dev->ReadNow();
    194   EXPECT_EQ(2u, dev->size());
    195   ui::TouchEvent* event = dev->event(1);
    196   EXPECT_FALSE(event == NULL);
    197 
    198   EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type());
    199   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
    200   EXPECT_EQ(42, event->x());
    201   EXPECT_EQ(43, event->y());
    202   EXPECT_EQ(0, event->touch_id());
    203   EXPECT_FLOAT_EQ(2.f / 3.f, event->force());
    204   EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
    205 
    206   dev->ConfigureReadMock(mock_kernel_queue_move2, 2, 0);
    207   dev->ReadNow();
    208   EXPECT_EQ(3u, dev->size());
    209   event = dev->event(2);
    210   EXPECT_FALSE(event == NULL);
    211 
    212   EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type());
    213   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
    214   EXPECT_EQ(42, event->x());
    215   EXPECT_EQ(42, event->y());
    216   EXPECT_EQ(0, event->touch_id());
    217   EXPECT_FLOAT_EQ(2.f / 3.f, event->force());
    218   EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
    219 }
    220 
    221 TEST_F(TouchEventConverterOzoneTest, TouchRelease) {
    222   ui::MockTouchEventConverterOzone* dev = device();
    223 
    224   struct input_event mock_kernel_queue_press[] = {
    225     {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
    226     {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
    227     {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
    228     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
    229     {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    230   };
    231 
    232   struct input_event mock_kernel_queue_release[] = {
    233     {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    234   };
    235 
    236   // Setup and discard a press.
    237   dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0);
    238   dev->ReadNow();
    239   EXPECT_EQ(1u, dev->size());
    240   ui::TouchEvent* event = dev->event(0);
    241   EXPECT_FALSE(event == NULL);
    242 
    243   dev->ConfigureReadMock(mock_kernel_queue_release, 2, 0);
    244   dev->ReadNow();
    245   EXPECT_EQ(2u, dev->size());
    246   event = dev->event(1);
    247   EXPECT_FALSE(event == NULL);
    248 
    249   EXPECT_EQ(ui::ET_TOUCH_RELEASED, event->type());
    250   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp());
    251   EXPECT_EQ(42, event->x());
    252   EXPECT_EQ(51, event->y());
    253   EXPECT_EQ(0, event->touch_id());
    254   EXPECT_FLOAT_EQ(.5f, event->force());
    255   EXPECT_FLOAT_EQ(0.f, event->rotation_angle());
    256 }
    257 
    258 TEST_F(TouchEventConverterOzoneTest, TwoFingerGesture) {
    259   ui::MockTouchEventConverterOzone* dev = device();
    260 
    261   ui::TouchEvent* ev0;
    262   ui::TouchEvent* ev1;
    263 
    264   struct input_event mock_kernel_queue_press0[] = {
    265     {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684},
    266     {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
    267     {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
    268     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42},
    269     {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    270   };
    271   // Setup and discard a press.
    272   dev->ConfigureReadMock(mock_kernel_queue_press0, 6, 0);
    273   dev->ReadNow();
    274   EXPECT_EQ(1u, dev->size());
    275 
    276   struct input_event mock_kernel_queue_move0[] = {
    277     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    278   };
    279   // Setup and discard a move.
    280   dev->ConfigureReadMock(mock_kernel_queue_move0, 2, 0);
    281   dev->ReadNow();
    282   EXPECT_EQ(2u, dev->size());
    283 
    284   struct input_event mock_kernel_queue_move0press1[] = {
    285     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0},
    286     {{0, 0}, EV_ABS, ABS_MT_SLOT, 1}, {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 686},
    287     {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3},
    288     {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45},
    289     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 101},
    290     {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 102}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    291   };
    292   // Move on 0, press on 1.
    293   dev->ConfigureReadMock(mock_kernel_queue_move0press1, 9, 0);
    294   dev->ReadNow();
    295   EXPECT_EQ(4u, dev->size());
    296   ev0 = dev->event(2);
    297   ev1 = dev->event(3);
    298 
    299   // Move
    300   EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type());
    301   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
    302   EXPECT_EQ(40, ev0->x());
    303   EXPECT_EQ(51, ev0->y());
    304   EXPECT_EQ(0, ev0->touch_id());
    305   EXPECT_FLOAT_EQ(.5f, ev0->force());
    306   EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
    307 
    308   // Press
    309   EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1->type());
    310   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
    311   EXPECT_EQ(101, ev1->x());
    312   EXPECT_EQ(102, ev1->y());
    313   EXPECT_EQ(1, ev1->touch_id());
    314   EXPECT_FLOAT_EQ(.5f, ev1->force());
    315   EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
    316 
    317   // Stationary 0, Moves 1.
    318   struct input_event mock_kernel_queue_stationary0_move1[] = {
    319     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    320   };
    321   dev->ConfigureReadMock(mock_kernel_queue_stationary0_move1, 2, 0);
    322   dev->ReadNow();
    323   EXPECT_EQ(5u, dev->size());
    324   ev1 = dev->event(4);
    325 
    326   EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type());
    327   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
    328   EXPECT_EQ(40, ev1->x());
    329   EXPECT_EQ(102, ev1->y());
    330   EXPECT_EQ(1, ev1->touch_id());
    331 
    332   EXPECT_FLOAT_EQ(.5f, ev1->force());
    333   EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
    334 
    335   // Move 0, stationary 1.
    336   struct input_event mock_kernel_queue_move0_stationary1[] = {
    337     {{0, 0}, EV_ABS, ABS_MT_SLOT, 0}, {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 39},
    338     {{0, 0}, EV_SYN, SYN_REPORT, 0}
    339   };
    340   dev->ConfigureReadMock(mock_kernel_queue_move0_stationary1, 3, 0);
    341   dev->ReadNow();
    342   EXPECT_EQ(6u, dev->size());
    343   ev0 = dev->event(5);
    344 
    345   EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type());
    346   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
    347   EXPECT_EQ(39, ev0->x());
    348   EXPECT_EQ(51, ev0->y());
    349   EXPECT_EQ(0, ev0->touch_id());
    350   EXPECT_FLOAT_EQ(.5f, ev0->force());
    351   EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
    352 
    353   // Release 0, move 1.
    354   struct input_event mock_kernel_queue_release0_move1[] = {
    355     {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_ABS, ABS_MT_SLOT, 1},
    356     {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 38}, {{0, 0}, EV_SYN, SYN_REPORT, 0}
    357   };
    358   dev->ConfigureReadMock(mock_kernel_queue_release0_move1, 4, 0);
    359   dev->ReadNow();
    360   EXPECT_EQ(8u, dev->size());
    361   ev0 = dev->event(6);
    362   ev1 = dev->event(7);
    363 
    364   EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0->type());
    365   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp());
    366   EXPECT_EQ(39, ev0->x());
    367   EXPECT_EQ(51, ev0->y());
    368   EXPECT_EQ(0, ev0->touch_id());
    369   EXPECT_FLOAT_EQ(.5f, ev0->force());
    370   EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle());
    371 
    372   EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type());
    373   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
    374   EXPECT_EQ(38, ev1->x());
    375   EXPECT_EQ(102, ev1->y());
    376   EXPECT_EQ(1, ev1->touch_id());
    377   EXPECT_FLOAT_EQ(.5f, ev1->force());
    378   EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
    379 
    380   // Release 1.
    381   struct input_event mock_kernel_queue_release1[] = {
    382     {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0},
    383   };
    384   dev->ConfigureReadMock(mock_kernel_queue_release1, 2, 0);
    385   dev->ReadNow();
    386   EXPECT_EQ(9u, dev->size());
    387   ev1 = dev->event(8);
    388 
    389   EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1->type());
    390   EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp());
    391   EXPECT_EQ(38, ev1->x());
    392   EXPECT_EQ(102, ev1->y());
    393   EXPECT_EQ(1, ev1->touch_id());
    394   EXPECT_FLOAT_EQ(.5f, ev1->force());
    395   EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle());
    396 }
    397