VirtualTouchpad_test.cpp revision 4b64dd48b6896d6b963f0a3a0259d3d2a7076a9e
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 11namespace android { 12namespace dvr { 13 14namespace { 15 16class 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// 31class 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 89class EvdevInjectorForTesting : public EvdevInjector { 90 public: 91 EvdevInjectorForTesting(UInput& uinput) { SetUInputForTesting(&uinput); } 92 const uinput_user_dev* GetUiDev() const { return GetUiDevForTesting(); } 93}; 94 95class VirtualTouchpadForTesting : public VirtualTouchpadEvdev { 96 public: 97 static sp<VirtualTouchpad> Create(EvdevInjectorForTesting& injector) { 98 VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting(); 99 touchpad->SetEvdevInjectorForTesting(&injector); 100 return sp<VirtualTouchpad>(touchpad); 101 } 102}; 103 104void DumpDifference(const char* expect, const char* actual) { 105 printf(" common: "); 106 while (*expect && *expect == *actual) { 107 putchar(*expect); 108 ++expect; 109 ++actual; 110 } 111 printf("\n expect: %s\n", expect); 112 printf(" actual: %s\n", actual); 113} 114 115} // anonymous namespace 116 117class VirtualTouchpadTest : public testing::Test {}; 118 119TEST_F(VirtualTouchpadTest, Goodness) { 120 UInputRecorder expect; 121 UInputRecorder record; 122 EvdevInjectorForTesting injector(record); 123 sp<VirtualTouchpad> touchpad(VirtualTouchpadForTesting::Create(injector)); 124 125 status_t touch_status = touchpad->Attach(); 126 EXPECT_EQ(0, touch_status); 127 128 // Check some aspects of uinput_user_dev. 129 const uinput_user_dev* uidev = injector.GetUiDev(); 130 for (int i = 0; i < ABS_CNT; ++i) { 131 EXPECT_EQ(0, uidev->absmin[i]); 132 EXPECT_EQ(0, uidev->absfuzz[i]); 133 EXPECT_EQ(0, uidev->absflat[i]); 134 if (i != ABS_MT_POSITION_X && i != ABS_MT_POSITION_Y && i != ABS_MT_SLOT) { 135 EXPECT_EQ(0, uidev->absmax[i]); 136 } 137 } 138 const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X]; 139 const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y]; 140 const int32_t slots = uidev->absmax[ABS_MT_SLOT]; 141 142 // Check the system calls performed by initialization. 143 // From ConfigureBegin(): 144 expect.Open(); 145 // From ConfigureInputProperty(INPUT_PROP_DIRECT): 146 expect.IoctlSetInt(UI_SET_PROPBIT, INPUT_PROP_DIRECT); 147 // From ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1): 148 expect.IoctlSetInt(UI_SET_EVBIT, EV_ABS); 149 expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_X); 150 expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y); 151 // From ConfigureAbsSlots(kSlots): 152 expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT); 153 // From ConfigureKey(BTN_TOUCH): 154 expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY); 155 expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH); 156 expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK); 157 // From ConfigureEnd(): 158 expect.Write(uidev, sizeof(uinput_user_dev)); 159 expect.IoctlVoid(UI_DEV_CREATE); 160 EXPECT_EQ(expect.GetString(), record.GetString()); 161 162 expect.Reset(); 163 record.Reset(); 164 touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0, 0, 0); 165 EXPECT_EQ(0, touch_status); 166 expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0); 167 expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0); 168 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0); 169 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0); 170 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 171 EXPECT_EQ(expect.GetString(), record.GetString()); 172 173 expect.Reset(); 174 record.Reset(); 175 touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 0.75f, 0.5f); 176 EXPECT_EQ(0, touch_status); 177 expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0); 178 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.25f * width); 179 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.75f * height); 180 expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_PRESS); 181 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 182 EXPECT_EQ(expect.GetString(), record.GetString()); 183 184 expect.Reset(); 185 record.Reset(); 186 touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.99f, 0.99f, 0.99f); 187 EXPECT_EQ(0, touch_status); 188 expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0); 189 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.99f * width); 190 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.99f * height); 191 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 192 EXPECT_EQ(expect.GetString(), record.GetString()); 193 194 expect.Reset(); 195 record.Reset(); 196 touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.0f, 1.0f, 1.0f); 197 EXPECT_EQ(EINVAL, touch_status); 198 EXPECT_EQ(expect.GetString(), record.GetString()); 199 200 expect.Reset(); 201 record.Reset(); 202 touch_status = 203 touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 0.75f, -0.01f); 204 EXPECT_EQ(0, touch_status); 205 expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_RELEASE); 206 expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, -1); 207 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 208 EXPECT_EQ(expect.GetString(), record.GetString()); 209 210 expect.Reset(); 211 record.Reset(); 212 touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY, 213 AMOTION_EVENT_BUTTON_BACK); 214 EXPECT_EQ(0, touch_status); 215 expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_PRESS); 216 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 217 EXPECT_EQ(expect.GetString(), record.GetString()); 218 219 expect.Reset(); 220 record.Reset(); 221 touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY, 222 AMOTION_EVENT_BUTTON_BACK); 223 EXPECT_EQ(0, touch_status); 224 EXPECT_EQ(expect.GetString(), record.GetString()); 225 226 expect.Reset(); 227 record.Reset(); 228 touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY, 0); 229 EXPECT_EQ(0, touch_status); 230 expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_RELEASE); 231 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 232 EXPECT_EQ(expect.GetString(), record.GetString()); 233 234 expect.Reset(); 235 record.Reset(); 236 touch_status = touchpad->Detach(); 237 EXPECT_EQ(0, touch_status); 238 expect.Close(); 239 EXPECT_EQ(expect.GetString(), record.GetString()); 240} 241 242TEST_F(VirtualTouchpadTest, Badness) { 243 UInputRecorder expect; 244 UInputRecorder record; 245 EvdevInjectorForTesting injector(record); 246 sp<VirtualTouchpad> touchpad(VirtualTouchpadForTesting::Create(injector)); 247 248 status_t touch_status = touchpad->Attach(); 249 EXPECT_EQ(0, touch_status); 250 251 // Touch off-screen should return an error, 252 // and should not result in any system calls. 253 expect.Reset(); 254 record.Reset(); 255 touch_status = 256 touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f); 257 EXPECT_NE(OK, touch_status); 258 touch_status = 259 touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, -0.75f, 1.0f); 260 EXPECT_NE(OK, touch_status); 261 touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.25f, 0.75f, 1.0f); 262 EXPECT_NE(OK, touch_status); 263 touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 1.75f, 1.0f); 264 EXPECT_NE(OK, touch_status); 265 EXPECT_EQ(expect.GetString(), record.GetString()); 266 267 // Unsupported button should return an error, 268 // and should not result in any system calls. 269 expect.Reset(); 270 record.Reset(); 271 touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY, 272 AMOTION_EVENT_BUTTON_FORWARD); 273 EXPECT_NE(OK, touch_status); 274 EXPECT_EQ(expect.GetString(), record.GetString()); 275 276 // Repeated attach is an error. 277 touch_status = touchpad->Attach(); 278 EXPECT_NE(0, touch_status); 279} 280 281} // namespace dvr 282} // namespace android 283