Home | History | Annotate | Download | only in tests
      1 #include <android/input.h>
      2 #include <gtest/gtest.h>
      3 #include <linux/input.h>
      4 #include <cstdio>
      5 #include <cstdlib>
      6 #include <cstring>
      7 
      8 #include "EvdevInjector.h"
      9 #include "VirtualTouchpadEvdev.h"
     10 
     11 namespace android {
     12 namespace dvr {
     13 
     14 namespace {
     15 
     16 class UInputForTesting : public EvdevInjector::UInput {
     17  public:
     18   ~UInputForTesting() override {}
     19   void WriteInputEvent(uint16_t type, uint16_t code, int32_t value) {
     20     struct input_event event;
     21     memset(&event, 0, sizeof(event));
     22     event.type = type;
     23     event.code = code;
     24     event.value = value;
     25     Write(&event, sizeof(event));
     26   }
     27 };
     28 
     29 // Recording test implementation of UInput.
     30 //
     31 class UInputRecorder : public UInputForTesting {
     32  public:
     33   UInputRecorder() {}
     34   ~UInputRecorder() override {}
     35 
     36   const std::string& GetString() const { return s_; }
     37   void Reset() { s_.clear(); }
     38 
     39   // UInput overrides:
     40 
     41   int Open() override {
     42     s_ += "o;";
     43     return 0;
     44   }
     45 
     46   int Close() override {
     47     s_ += "c;";
     48     return 0;
     49   }
     50 
     51   int Write(const void* buf, size_t count) override {
     52     s_ += "w(";
     53     s_ += Encode(&count, sizeof(count));
     54     s_ += ",";
     55     s_ += Encode(buf, count);
     56     s_ += ");";
     57     return 0;
     58   }
     59 
     60   int IoctlVoid(int request) override {
     61     s_ += "i(";
     62     s_ += Encode(&request, sizeof(request));
     63     s_ += ");";
     64     return 0;
     65   }
     66 
     67   int IoctlSetInt(int request, int value) override {
     68     s_ += "i(";
     69     s_ += Encode(&request, sizeof(request));
     70     s_ += ",";
     71     s_ += Encode(&value, sizeof(value));
     72     s_ += ");";
     73     return 0;
     74   }
     75 
     76  private:
     77   std::string s_;
     78 
     79   std::string Encode(const void* buf, size_t count) {
     80     const char* in = static_cast<const char*>(buf);
     81     char out[2 * count + 1];
     82     for (size_t i = 0; i < count; ++i) {
     83       snprintf(&out[2 * i], 3, "%02X", in[i]);
     84     }
     85     return out;
     86   }
     87 };
     88 
     89 class EvdevInjectorForTesting : public EvdevInjector {
     90  public:
     91   EvdevInjectorForTesting() { SetUInputForTesting(&record); }
     92   const uinput_user_dev* GetUiDev() const { return GetUiDevForTesting(); }
     93   UInputRecorder record;
     94 };
     95 
     96 class VirtualTouchpadForTesting : public VirtualTouchpadEvdev {
     97  public:
     98   static std::unique_ptr<VirtualTouchpad> Create() {
     99     return std::unique_ptr<VirtualTouchpad>(New());
    100   }
    101   static VirtualTouchpadForTesting* New() {
    102     VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting();
    103     touchpad->Reset();
    104     for (int t = 0; t < kTouchpads; ++t) {
    105       touchpad->SetEvdevInjectorForTesting(t, &touchpad->injector[t]);
    106     }
    107     return touchpad;
    108   }
    109   int GetTouchpadCount() const { return kTouchpads; }
    110   EvdevInjectorForTesting injector[kTouchpads];
    111 };
    112 
    113 }  // anonymous namespace
    114 
    115 class VirtualTouchpadTest : public testing::Test {};
    116 
    117 TEST_F(VirtualTouchpadTest, Goodness) {
    118   std::unique_ptr<VirtualTouchpadForTesting> touchpad(
    119       VirtualTouchpadForTesting::New());
    120   UInputRecorder expect;
    121 
    122   status_t touch_status = touchpad->Attach();
    123   EXPECT_EQ(0, touch_status);
    124 
    125   // Check some aspects of uinput_user_dev.
    126   const uinput_user_dev* uidev;
    127   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    128     SCOPED_TRACE(t);
    129     uidev = touchpad->injector[t].GetUiDev();
    130     String8 name;
    131     name.appendFormat("vr-virtual-touchpad-%d", t);
    132     EXPECT_EQ(name, uidev->name);
    133     for (int i = 0; i < ABS_CNT; ++i) {
    134       EXPECT_EQ(0, uidev->absmin[i]);
    135       EXPECT_EQ(0, uidev->absfuzz[i]);
    136       EXPECT_EQ(0, uidev->absflat[i]);
    137       if (i != ABS_MT_POSITION_X && i != ABS_MT_POSITION_Y &&
    138           i != ABS_MT_SLOT) {
    139         EXPECT_EQ(0, uidev->absmax[i]);
    140       }
    141     }
    142   }
    143   const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X];
    144   const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y];
    145 
    146   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    147     SCOPED_TRACE(t);
    148     // Check the system calls performed by initialization.
    149     expect.Reset();
    150     // From ConfigureBegin():
    151     expect.Open();
    152     // From ConfigureInputProperty(INPUT_PROP_DIRECT):
    153     expect.IoctlSetInt(UI_SET_PROPBIT, INPUT_PROP_DIRECT);
    154     // From ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1):
    155     expect.IoctlSetInt(UI_SET_EVBIT, EV_ABS);
    156     expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_X);
    157     expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y);
    158     // From ConfigureAbsSlots(kSlots):
    159     expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT);
    160     // From ConfigureRel(REL_WHEEL):
    161     expect.IoctlSetInt(UI_SET_EVBIT, EV_REL);
    162     expect.IoctlSetInt(UI_SET_RELBIT, REL_WHEEL);
    163     // From ConfigureRel(REL_HWHEEL):
    164     expect.IoctlSetInt(UI_SET_RELBIT, REL_HWHEEL);
    165     // From ConfigureKey(BTN_TOUCH):
    166     expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
    167     expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
    168     expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK);
    169     // From ConfigureEnd():
    170     expect.Write(touchpad->injector[t].GetUiDev(), sizeof(uinput_user_dev));
    171     expect.IoctlVoid(UI_DEV_CREATE);
    172     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    173   }
    174 
    175   expect.Reset();
    176   expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0);
    177   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
    178   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0);
    179   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0);
    180   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
    181   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    182     SCOPED_TRACE(t);
    183     touchpad->injector[t].record.Reset();
    184     touch_status = touchpad->Touch(t, 0, 0, 0);
    185     EXPECT_EQ(0, touch_status);
    186     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    187   }
    188 
    189   expect.Reset();
    190   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
    191   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.25f * width);
    192   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.75f * height);
    193   expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_PRESS);
    194   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
    195   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    196     SCOPED_TRACE(t);
    197     touchpad->injector[t].record.Reset();
    198     touch_status = touchpad->Touch(t, 0.25f, 0.75f, 0.5f);
    199     EXPECT_EQ(0, touch_status);
    200     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    201   }
    202 
    203   expect.Reset();
    204   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
    205   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.99f * width);
    206   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.99f * height);
    207   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
    208   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    209     SCOPED_TRACE(t);
    210     touchpad->injector[t].record.Reset();
    211     touch_status = touchpad->Touch(t, 0.99f, 0.99f, 0.99f);
    212     EXPECT_EQ(0, touch_status);
    213     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    214   }
    215 
    216   expect.Reset();
    217   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    218     SCOPED_TRACE(t);
    219     touchpad->injector[t].record.Reset();
    220     touch_status = touchpad->Touch(t, 1.0f, 1.0f, 1.0f);
    221     EXPECT_EQ(EINVAL, touch_status);
    222     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    223   }
    224 
    225   expect.Reset();
    226   expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_RELEASE);
    227   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, -1);
    228   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
    229   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    230     SCOPED_TRACE(t);
    231     touchpad->injector[t].record.Reset();
    232     touch_status = touchpad->Touch(t, 0.25f, 0.75f, -0.01f);
    233     EXPECT_EQ(0, touch_status);
    234     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    235   }
    236 
    237   expect.Reset();
    238   expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_PRESS);
    239   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
    240   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    241     SCOPED_TRACE(t);
    242     touchpad->injector[t].record.Reset();
    243     touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
    244     EXPECT_EQ(0, touch_status);
    245     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    246   }
    247 
    248   expect.Reset();
    249   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    250     SCOPED_TRACE(t);
    251     touchpad->injector[t].record.Reset();
    252     touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
    253     EXPECT_EQ(0, touch_status);
    254     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    255   }
    256 
    257   expect.Reset();
    258   expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_RELEASE);
    259   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
    260   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    261     SCOPED_TRACE(t);
    262     touchpad->injector[t].record.Reset();
    263     touch_status = touchpad->ButtonState(t, 0);
    264     EXPECT_EQ(0, touch_status);
    265     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    266   }
    267 
    268   expect.Reset();
    269   expect.Close();
    270   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    271     SCOPED_TRACE(t);
    272     touchpad->injector[t].record.Reset();
    273   }
    274   touch_status = touchpad->Detach();
    275   EXPECT_EQ(0, touch_status);
    276   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
    277     SCOPED_TRACE(t);
    278     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
    279   }
    280 }
    281 
    282 TEST_F(VirtualTouchpadTest, Badness) {
    283   std::unique_ptr<VirtualTouchpadForTesting> touchpad(
    284       VirtualTouchpadForTesting::New());
    285   UInputRecorder expect;
    286   UInputRecorder& record = touchpad->injector[VirtualTouchpad::PRIMARY].record;
    287 
    288   status_t touch_status = touchpad->Attach();
    289   EXPECT_EQ(0, touch_status);
    290 
    291   // Touch off-screen should return an error,
    292   // and should not result in any system calls.
    293   expect.Reset();
    294   record.Reset();
    295   touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f);
    296   EXPECT_NE(OK, touch_status);
    297   touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, -0.75f, 1.0f);
    298   EXPECT_NE(OK, touch_status);
    299   touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.25f, 0.75f, 1.0f);
    300   EXPECT_NE(OK, touch_status);
    301   touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 1.75f, 1.0f);
    302   EXPECT_NE(OK, touch_status);
    303   EXPECT_EQ(expect.GetString(), record.GetString());
    304 
    305   // Unsupported button should return an error,
    306   // and should not result in any system calls.
    307   expect.Reset();
    308   record.Reset();
    309   touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY,
    310                                        AMOTION_EVENT_BUTTON_FORWARD);
    311   EXPECT_NE(OK, touch_status);
    312   EXPECT_EQ(expect.GetString(), record.GetString());
    313 
    314   // Repeated attach is an error.
    315   touch_status = touchpad->Attach();
    316   EXPECT_NE(0, touch_status);
    317 }
    318 
    319 }  // namespace dvr
    320 }  // namespace android
    321