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 Vakulenkovoid DumpDifference(const char* expect, const char* actual) {
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf("  common: ");
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (*expect && *expect == *actual) {
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    putchar(*expect);
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ++expect;
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ++actual;
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf("\n  expect: %s\n", expect);
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf("  actual: %s\n", actual);
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
12689af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedelclass VirtualTouchpadTest : public testing::Test {};
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(VirtualTouchpadTest, Goodness) {
129de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel  std::unique_ptr<VirtualTouchpadForTesting> touchpad(
130de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel      VirtualTouchpadForTesting::New());
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  UInputRecorder expect;
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1334b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  status_t touch_status = touchpad->Attach();
1344b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  EXPECT_EQ(0, touch_status);
1354b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Check some aspects of uinput_user_dev.
1370108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  const uinput_user_dev* uidev;
1380108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
1390108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
1400108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    uidev = touchpad->injector[t].GetUiDev();
1410108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    String8 name;
142fa5cf46ac7b84cc20bf29e5b8c298a84b407b1e3Santos Cordon    name.appendFormat("vr-virtual-touchpad-%d", t);
1430108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(name, uidev->name);
1440108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    for (int i = 0; i < ABS_CNT; ++i) {
1450108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      EXPECT_EQ(0, uidev->absmin[i]);
1460108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      EXPECT_EQ(0, uidev->absfuzz[i]);
1470108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      EXPECT_EQ(0, uidev->absflat[i]);
1480108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      if (i != ABS_MT_POSITION_X && i != ABS_MT_POSITION_Y &&
1490108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel          i != ABS_MT_SLOT) {
1500108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel        EXPECT_EQ(0, uidev->absmax[i]);
1510108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel      }
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X];
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y];
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int32_t slots = uidev->absmax[ABS_MT_SLOT];
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1580108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
1590108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
1600108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // Check the system calls performed by initialization.
1610108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.Reset();
1620108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureBegin():
1630108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.Open();
1640108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureInputProperty(INPUT_PROP_DIRECT):
1650108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_PROPBIT, INPUT_PROP_DIRECT);
1660108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1):
1670108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_EVBIT, EV_ABS);
1680108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_X);
1690108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y);
1700108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureAbsSlots(kSlots):
1710108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT);
172b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    // From ConfigureRel(REL_WHEEL):
173b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    expect.IoctlSetInt(UI_SET_EVBIT, EV_REL);
174b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    expect.IoctlSetInt(UI_SET_RELBIT, REL_WHEEL);
175b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    // From ConfigureRel(REL_HWHEEL):
176b2990034866e4f2cce6166b1c1d77dec27770686Kevin Schoedel    expect.IoctlSetInt(UI_SET_RELBIT, REL_HWHEEL);
1770108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureKey(BTN_TOUCH):
1780108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
1790108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
1800108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK);
1810108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    // From ConfigureEnd():
1820108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.Write(touchpad->injector[t].GetUiDev(), sizeof(uinput_user_dev));
1830108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    expect.IoctlVoid(UI_DEV_CREATE);
1840108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
1850108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0);
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0);
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0);
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
1930108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
1940108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
1950108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
1960108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->Touch(t, 0, 0, 0);
1970108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
1980108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
1990108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.25f * width);
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.75f * height);
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_PRESS);
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
2070108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2080108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2090108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2100108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->Touch(t, 0.25f, 0.75f, 0.5f);
2110108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2120108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2130108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
2174b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.99f * width);
2184b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.99f * height);
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
2200108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2210108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2220108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2230108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->Touch(t, 0.99f, 0.99f, 0.99f);
2240108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2250108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2260108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
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, 1.0f, 1.0f, 1.0f);
2330108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(EINVAL, touch_status);
2340108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2350108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
2364b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel
2374b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  expect.Reset();
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_RELEASE);
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, -1);
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
2410108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2420108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2430108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2440108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->Touch(t, 0.25f, 0.75f, -0.01f);
2450108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2460108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2470108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  expect.Reset();
25043b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_PRESS);
25143b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
2520108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2530108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2540108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2550108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
2560108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2570108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2580108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
25943b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
26043b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
2610108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2620108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2630108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2640108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
2650108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2660108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2670108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
26843b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
26943b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
27043b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_RELEASE);
27143b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
2720108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2730108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2740108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2750108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touch_status = touchpad->ButtonState(t, 0);
2760108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(0, touch_status);
2770108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2780108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
27943b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
28043b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
2810108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  expect.Close();
2820108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2830108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2840108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    touchpad->injector[t].record.Reset();
2850108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
2864b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  touch_status = touchpad->Detach();
2874b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  EXPECT_EQ(0, touch_status);
2880108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
2890108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    SCOPED_TRACE(t);
2900108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel    EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
2910108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  }
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(VirtualTouchpadTest, Badness) {
295de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel  std::unique_ptr<VirtualTouchpadForTesting> touchpad(
296de1cdaebc9b8fdbc5348e6c07f849b74bacc485dKevin Schoedel      VirtualTouchpadForTesting::New());
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  UInputRecorder expect;
2980108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  UInputRecorder& record = touchpad->injector[VirtualTouchpad::PRIMARY].record;
29943b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
3004b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  status_t touch_status = touchpad->Attach();
3014b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  EXPECT_EQ(0, touch_status);
3024b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel
30343b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  // Touch off-screen should return an error,
30443b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  // and should not result in any system calls.
30543b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
30643b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  record.Reset();
3070108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f);
30889af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
3090108af72a8d8d2ee2af127b4c099b340ad63e3f8Kevin Schoedel  touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, -0.75f, 1.0f);
31089af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
3113002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel  touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.25f, 0.75f, 1.0f);
31289af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
3133002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel  touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 1.75f, 1.0f);
31489af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
31543b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  EXPECT_EQ(expect.GetString(), record.GetString());
31643b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel
31743b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  // Unsupported button should return an error,
31843b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  // and should not result in any system calls.
31943b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  expect.Reset();
32043b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  record.Reset();
3213002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel  touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY,
3223002b8a74431dd7c005269cf9306443a4b4963f1Kevin Schoedel                                       AMOTION_EVENT_BUTTON_FORWARD);
32389af70bce420f011adfeb0f80984b3895c4d7d9bKevin Schoedel  EXPECT_NE(OK, touch_status);
32443b5b06c8be24e465bd6a7b22a8d341db1ad50a2Kevin Schoedel  EXPECT_EQ(expect.GetString(), record.GetString());
3254b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel
3264b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  // Repeated attach is an error.
3274b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  touch_status = touchpad->Attach();
3284b64dd48b6896d6b963f0a3a0259d3d2a7076a9eKevin Schoedel  EXPECT_NE(0, touch_status);
329e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
330e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
331e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace dvr
332e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
333