• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
~UInputForTesting()18   ~UInputForTesting() override {}
WriteInputEvent(uint16_t type,uint16_t code,int32_t value)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:
UInputRecorder()33   UInputRecorder() {}
~UInputRecorder()34   ~UInputRecorder() override {}
35 
GetString() const36   const std::string& GetString() const { return s_; }
Reset()37   void Reset() { s_.clear(); }
38 
39   // UInput overrides:
40 
Open()41   int Open() override {
42     s_ += "o;";
43     return 0;
44   }
45 
Close()46   int Close() override {
47     s_ += "c;";
48     return 0;
49   }
50 
Write(const void * buf,size_t count)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 
IoctlVoid(int request)60   int IoctlVoid(int request) override {
61     s_ += "i(";
62     s_ += Encode(&request, sizeof(request));
63     s_ += ");";
64     return 0;
65   }
66 
IoctlSetInt(int request,int value)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 
Encode(const void * buf,size_t count)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:
EvdevInjectorForTesting()91   EvdevInjectorForTesting() { SetUInputForTesting(&record); }
GetUiDev() const92   const uinput_user_dev* GetUiDev() const { return GetUiDevForTesting(); }
93   UInputRecorder record;
94 };
95 
96 class VirtualTouchpadForTesting : public VirtualTouchpadEvdev {
97  public:
Create()98   static std::unique_ptr<VirtualTouchpad> Create() {
99     return std::unique_ptr<VirtualTouchpad>(New());
100   }
New()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   }
GetTouchpadCount() const109   int GetTouchpadCount() const { return kTouchpads; }
110   EvdevInjectorForTesting injector[kTouchpads];
111 };
112 
DumpDifference(const char * expect,const char * actual)113 void DumpDifference(const char* expect, const char* actual) {
114   printf("  common: ");
115   while (*expect && *expect == *actual) {
116     putchar(*expect);
117     ++expect;
118     ++actual;
119   }
120   printf("\n  expect: %s\n", expect);
121   printf("  actual: %s\n", actual);
122 }
123 
124 }  // anonymous namespace
125 
126 class VirtualTouchpadTest : public testing::Test {};
127 
TEST_F(VirtualTouchpadTest,Goodness)128 TEST_F(VirtualTouchpadTest, Goodness) {
129   std::unique_ptr<VirtualTouchpadForTesting> touchpad(
130       VirtualTouchpadForTesting::New());
131   UInputRecorder expect;
132 
133   status_t touch_status = touchpad->Attach();
134   EXPECT_EQ(0, touch_status);
135 
136   // Check some aspects of uinput_user_dev.
137   const uinput_user_dev* uidev;
138   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
139     SCOPED_TRACE(t);
140     uidev = touchpad->injector[t].GetUiDev();
141     String8 name;
142     name.appendFormat("vr-virtual-touchpad-%d", t);
143     EXPECT_EQ(name, uidev->name);
144     for (int i = 0; i < ABS_CNT; ++i) {
145       EXPECT_EQ(0, uidev->absmin[i]);
146       EXPECT_EQ(0, uidev->absfuzz[i]);
147       EXPECT_EQ(0, uidev->absflat[i]);
148       if (i != ABS_MT_POSITION_X && i != ABS_MT_POSITION_Y &&
149           i != ABS_MT_SLOT) {
150         EXPECT_EQ(0, uidev->absmax[i]);
151       }
152     }
153   }
154   const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X];
155   const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y];
156   const int32_t slots = uidev->absmax[ABS_MT_SLOT];
157 
158   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
159     SCOPED_TRACE(t);
160     // Check the system calls performed by initialization.
161     expect.Reset();
162     // From ConfigureBegin():
163     expect.Open();
164     // From ConfigureInputProperty(INPUT_PROP_DIRECT):
165     expect.IoctlSetInt(UI_SET_PROPBIT, INPUT_PROP_DIRECT);
166     // From ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1):
167     expect.IoctlSetInt(UI_SET_EVBIT, EV_ABS);
168     expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_X);
169     expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y);
170     // From ConfigureAbsSlots(kSlots):
171     expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT);
172     // From ConfigureKey(BTN_TOUCH):
173     expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
174     expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
175     expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK);
176     // From ConfigureEnd():
177     expect.Write(touchpad->injector[t].GetUiDev(), sizeof(uinput_user_dev));
178     expect.IoctlVoid(UI_DEV_CREATE);
179     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
180   }
181 
182   expect.Reset();
183   expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0);
184   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
185   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0);
186   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0);
187   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
188   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
189     SCOPED_TRACE(t);
190     touchpad->injector[t].record.Reset();
191     touch_status = touchpad->Touch(t, 0, 0, 0);
192     EXPECT_EQ(0, touch_status);
193     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
194   }
195 
196   expect.Reset();
197   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
198   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.25f * width);
199   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.75f * height);
200   expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_PRESS);
201   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
202   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
203     SCOPED_TRACE(t);
204     touchpad->injector[t].record.Reset();
205     touch_status = touchpad->Touch(t, 0.25f, 0.75f, 0.5f);
206     EXPECT_EQ(0, touch_status);
207     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
208   }
209 
210   expect.Reset();
211   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
212   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.99f * width);
213   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.99f * height);
214   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
215   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
216     SCOPED_TRACE(t);
217     touchpad->injector[t].record.Reset();
218     touch_status = touchpad->Touch(t, 0.99f, 0.99f, 0.99f);
219     EXPECT_EQ(0, touch_status);
220     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
221   }
222 
223   expect.Reset();
224   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
225     SCOPED_TRACE(t);
226     touchpad->injector[t].record.Reset();
227     touch_status = touchpad->Touch(t, 1.0f, 1.0f, 1.0f);
228     EXPECT_EQ(EINVAL, touch_status);
229     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
230   }
231 
232   expect.Reset();
233   expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_RELEASE);
234   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, -1);
235   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
236   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
237     SCOPED_TRACE(t);
238     touchpad->injector[t].record.Reset();
239     touch_status = touchpad->Touch(t, 0.25f, 0.75f, -0.01f);
240     EXPECT_EQ(0, touch_status);
241     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
242   }
243 
244   expect.Reset();
245   expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_PRESS);
246   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
247   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
248     SCOPED_TRACE(t);
249     touchpad->injector[t].record.Reset();
250     touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
251     EXPECT_EQ(0, touch_status);
252     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
253   }
254 
255   expect.Reset();
256   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
257     SCOPED_TRACE(t);
258     touchpad->injector[t].record.Reset();
259     touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
260     EXPECT_EQ(0, touch_status);
261     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
262   }
263 
264   expect.Reset();
265   expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_RELEASE);
266   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
267   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
268     SCOPED_TRACE(t);
269     touchpad->injector[t].record.Reset();
270     touch_status = touchpad->ButtonState(t, 0);
271     EXPECT_EQ(0, touch_status);
272     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
273   }
274 
275   expect.Reset();
276   expect.Close();
277   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
278     SCOPED_TRACE(t);
279     touchpad->injector[t].record.Reset();
280   }
281   touch_status = touchpad->Detach();
282   EXPECT_EQ(0, touch_status);
283   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
284     SCOPED_TRACE(t);
285     EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
286   }
287 }
288 
TEST_F(VirtualTouchpadTest,Badness)289 TEST_F(VirtualTouchpadTest, Badness) {
290   std::unique_ptr<VirtualTouchpadForTesting> touchpad(
291       VirtualTouchpadForTesting::New());
292   UInputRecorder expect;
293   UInputRecorder& record = touchpad->injector[VirtualTouchpad::PRIMARY].record;
294 
295   status_t touch_status = touchpad->Attach();
296   EXPECT_EQ(0, touch_status);
297 
298   // Touch off-screen should return an error,
299   // and should not result in any system calls.
300   expect.Reset();
301   record.Reset();
302   touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f);
303   EXPECT_NE(OK, touch_status);
304   touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, -0.75f, 1.0f);
305   EXPECT_NE(OK, touch_status);
306   touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.25f, 0.75f, 1.0f);
307   EXPECT_NE(OK, touch_status);
308   touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 1.75f, 1.0f);
309   EXPECT_NE(OK, touch_status);
310   EXPECT_EQ(expect.GetString(), record.GetString());
311 
312   // Unsupported button should return an error,
313   // and should not result in any system calls.
314   expect.Reset();
315   record.Reset();
316   touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY,
317                                        AMOTION_EVENT_BUTTON_FORWARD);
318   EXPECT_NE(OK, touch_status);
319   EXPECT_EQ(expect.GetString(), record.GetString());
320 
321   // Repeated attach is an error.
322   touch_status = touchpad->Attach();
323   EXPECT_NE(0, touch_status);
324 }
325 
326 }  // namespace dvr
327 }  // namespace android
328