143b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel#include <android/input.h>
289af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel#include <gtest/gtest.h>
389af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel#include <linux/input.h>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <cstdio>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <cstdlib>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <cstring>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "EvdevInjector.h"
989af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel#include "VirtualTouchpadEvdev.h"
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace dvr {
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass UInputForTesting : public EvdevInjector::UInput {
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
183002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel  ~UInputForTesting() override {}
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void WriteInputEvent(uint16_t type, uint16_t code, int32_t value) {
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    struct input_event event;
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    memset(&event, 0, sizeof(event));
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    event.type = type;
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    event.code = code;
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    event.value = value;
2589af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel    Write(&event, sizeof(event));
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Recording test implementation of UInput.
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko//
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass UInputRecorder : public UInputForTesting {
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  UInputRecorder() {}
343002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel  ~UInputRecorder() override {}
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const std::string& GetString() const { return s_; }
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void Reset() { s_.clear(); }
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // UInput overrides:
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Open() override {
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += "o;";
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Close() override {
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += "c;";
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Write(const void* buf, size_t count) override {
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += "w(";
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += Encode(&count, sizeof(count));
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += ",";
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += Encode(buf, count);
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += ");";
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int IoctlVoid(int request) override {
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += "i(";
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += Encode(&request, sizeof(request));
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += ");";
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int IoctlSetInt(int request, int value) override {
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += "i(";
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += Encode(&request, sizeof(request));
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += ",";
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += Encode(&value, sizeof(value));
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    s_ += ");";
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::string s_;
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::string Encode(const void* buf, size_t count) {
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const char* in = static_cast<const char*>(buf);
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    char out[2 * count + 1];
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    for (size_t i = 0; i < count; ++i) {
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      snprintf(&out[2 * i], 3, "%02X", in[i]);
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return out;
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass EvdevInjectorForTesting : public EvdevInjector {
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
910108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  EvdevInjectorForTesting() { SetUInputForTesting(&record); }
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const uinput_user_dev* GetUiDev() const { return GetUiDevForTesting(); }
930108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  UInputRecorder record;
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
9689af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedelclass VirtualTouchpadForTesting : public VirtualTouchpadEvdev {
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
98de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel  static std::unique_ptr<VirtualTouchpad> Create() {
99de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel    return std::unique_ptr<VirtualTouchpad>(New());
100de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel  }
1010108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  static VirtualTouchpadForTesting* New() {
10289af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel    VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting();
1030108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->Reset();
1040108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    for (int t = 0; t < kTouchpads; ++t) {
1050108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      touchpad->SetEvdevInjectorForTesting(t, &touchpad->injector[t]);
1060108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    }
1070108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    return touchpad;
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
1090108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  int GetTouchpadCount() const { return kTouchpads; }
1100108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  EvdevInjectorForTesting injector[kTouchpads];
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
11589af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedelclass VirtualTouchpadTest : public testing::Test {};
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(VirtualTouchpadTest, Goodness) {
118de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel  std::unique_ptr<VirtualTouchpadForTesting> touchpad(
119de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel      VirtualTouchpadForTesting::New());
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  UInputRecorder expect;
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1224b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  status_t touch_status = touchpad->Attach();
1234b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  EXPECT_EQ(0, touch_status);
1244b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Check some aspects of uinput_user_dev.
1260108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  const uinput_user_dev* uidev;
1270108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
1280108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
1290108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    uidev = touchpad->injector[t].GetUiDev();
1300108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    String8 name;
131fa5cf46ac7b84cc20bf29e5b8c298a84b407b1e3Santos Cordon    name.appendFormat("vr-virtual-touchpad-%d", t);
1320108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(name, uidev->name);
1330108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    for (int i = 0; i < ABS_CNT; ++i) {
1340108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      EXPECT_EQ(0, uidev->absmin[i]);
1350108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      EXPECT_EQ(0, uidev->absfuzz[i]);
1360108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      EXPECT_EQ(0, uidev->absflat[i]);
1370108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      if (i != ABS_MT_POSITION_X && i != ABS_MT_POSITION_Y &&
1380108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel          i != ABS_MT_SLOT) {
1390108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel        EXPECT_EQ(0, uidev->absmax[i]);
1400108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      }
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X];
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y];
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1460108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
1470108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
1480108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // Check the system calls performed by initialization.
1490108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.Reset();
1500108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureBegin():
1510108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.Open();
1520108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureInputProperty(INPUT_PROP_DIRECT):
1530108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_PROPBIT, INPUT_PROP_DIRECT);
1540108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1):
1550108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_EVBIT, EV_ABS);
1560108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_X);
1570108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y);
1580108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureAbsSlots(kSlots):
1590108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT);
160b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    // From ConfigureRel(REL_WHEEL):
161b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    expect.IoctlSetInt(UI_SET_EVBIT, EV_REL);
162b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    expect.IoctlSetInt(UI_SET_RELBIT, REL_WHEEL);
163b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    // From ConfigureRel(REL_HWHEEL):
164b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    expect.IoctlSetInt(UI_SET_RELBIT, REL_HWHEEL);
1650108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureKey(BTN_TOUCH):
1660108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
1670108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
1680108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK);
1690108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureEnd():
1700108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.Write(touchpad->injector[t].GetUiDev(), sizeof(uinput_user_dev));
1710108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlVoid(UI_DEV_CREATE);
1720108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
1730108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0);
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0);
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0);
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
1810108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
1820108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
1830108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
1840108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->Touch(t, 0, 0, 0);
1850108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
1860108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
1870108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.25f * width);
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.75f * height);
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_PRESS);
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
1950108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
1960108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
1970108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
1980108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->Touch(t, 0.25f, 0.75f, 0.5f);
1990108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2000108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2010108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
2054b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.99f * width);
2064b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.99f * height);
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
2080108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2090108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2100108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2110108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->Touch(t, 0.99f, 0.99f, 0.99f);
2120108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2130108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2140108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
2170108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2180108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2190108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2200108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->Touch(t, 1.0f, 1.0f, 1.0f);
2210108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(EINVAL, touch_status);
2220108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2230108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
2244b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel
2254b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  expect.Reset();
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_RELEASE);
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, -1);
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
2290108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2300108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2310108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2320108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->Touch(t, 0.25f, 0.75f, -0.01f);
2330108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2340108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2350108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
23843b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_PRESS);
23943b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
2400108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2410108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2420108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2430108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
2440108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2450108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2460108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
24743b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
24843b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
2490108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2500108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2510108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2520108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
2530108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2540108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2550108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
25643b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
25743b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
25843b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_RELEASE);
25943b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
2600108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2610108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2620108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2630108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->ButtonState(t, 0);
2640108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2650108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2660108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
26743b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
26843b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
2690108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  expect.Close();
2700108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2710108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2720108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2730108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
2744b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  touch_status = touchpad->Detach();
2754b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  EXPECT_EQ(0, touch_status);
2760108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2770108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2780108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2790108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(VirtualTouchpadTest, Badness) {
283de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel  std::unique_ptr<VirtualTouchpadForTesting> touchpad(
284de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel      VirtualTouchpadForTesting::New());
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  UInputRecorder expect;
2860108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  UInputRecorder& record = touchpad->injector[VirtualTouchpad::PRIMARY].record;
28743b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
2884b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  status_t touch_status = touchpad->Attach();
2894b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  EXPECT_EQ(0, touch_status);
2904b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel
29143b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  // Touch off-screen should return an error,
29243b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  // and should not result in any system calls.
29343b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
29443b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  record.Reset();
2950108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f);
29689af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
2970108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, -0.75f, 1.0f);
29889af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
2993002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel  touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.25f, 0.75f, 1.0f);
30089af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
3013002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel  touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 1.75f, 1.0f);
30289af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
30343b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  EXPECT_EQ(expect.GetString(), record.GetString());
30443b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
30543b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  // Unsupported button should return an error,
30643b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  // and should not result in any system calls.
30743b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
30843b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  record.Reset();
3093002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel  touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY,
3103002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel                                       AMOTION_EVENT_BUTTON_FORWARD);
31189af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
31243b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  EXPECT_EQ(expect.GetString(), record.GetString());
3134b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel
3144b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  // Repeated attach is an error.
3154b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  touch_status = touchpad->Attach();
3164b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  EXPECT_NE(0, touch_status);
317e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
318e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace dvr
320e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
321