1#ifndef ANDROID_DVR_EVDEV_INJECTOR_H
2#define ANDROID_DVR_EVDEV_INJECTOR_H
3
4#include <android-base/unique_fd.h>
5#include <linux/uinput.h>
6#include <utils/String8.h>
7
8#include <cstdint>
9#include <memory>
10#include <unordered_set>
11
12namespace android {
13namespace dvr {
14
15// Simulated evdev input device.
16//
17class EvdevInjector {
18 public:
19  // EvdevInjector-specific error codes are negative integers; other non-zero
20  // values returned from public routines are |errno| codes from underlying I/O.
21  // EvdevInjector maintains a 'sticky' error state, similar to |errno|, so that
22  // a caller can perform a sequence of operations and check for errors at the
23  // end using |GetError()|. In general, the first such error will be recorded
24  // and will suppress effects of further device operations until |ResetError()|
25  // is called.
26  //
27  enum : int {
28    ERROR_DEVICE_NAME = -1,     // Invalid device name.
29    ERROR_PROPERTY_RANGE = -2,  // |INPUT_PROP_*| code out of range.
30    ERROR_KEY_RANGE = -3,       // |KEY_*|/|BTN_*| code out of range.
31    ERROR_ABS_RANGE = -4,       // |ABS_*| code out of range.
32    ERROR_SEQUENCING = -5,      // Configure/Send out of order.
33    ERROR_REL_RANGE = -6,       // |REL_*| code out of range.
34  };
35
36  // Key event |value| is not defined in <linux/input.h>.
37  enum : int32_t { KEY_RELEASE = 0, KEY_PRESS = 1, KEY_REPEAT = 2 };
38
39  // UInput provides a shim to intercept /dev/uinput operations
40  // just above the system call level, for testing.
41  //
42  class UInput {
43   public:
44    UInput() {}
45    virtual ~UInput() {}
46    virtual int Open();
47    virtual int Close();
48    virtual int Write(const void* buf, size_t count);
49    virtual int IoctlVoid(int request);
50    virtual int IoctlSetInt(int request, int value);
51
52   private:
53    base::unique_fd fd_;
54  };
55
56  EvdevInjector() {}
57  ~EvdevInjector() { Close(); }
58  void Close();
59
60  int GetError() const { return error_; }
61  void ResetError() { error_ = 0; }
62
63  // Configuration must be performed before sending any events.
64  // |ConfigureBegin()| must be called first, and |ConfigureEnd()| last,
65  // with zero or more other |Configure...()| calls in between in any order.
66
67  // Configure the basic evdev device properties; must be called first.
68  int ConfigureBegin(const char* device_name, int16_t bustype, int16_t vendor,
69                     int16_t product, int16_t version);
70
71  // Configure an optional input device property.
72  // @param property  One of the |INPUT_PROP_*| constants from <linux/input.h>.
73  int ConfigureInputProperty(int property);
74
75  // Configure an input key.
76  // @param key One of the |KEY_*| or |BTN_*| constants from <linux/input.h>.
77  int ConfigureKey(uint16_t key);
78
79  // Configure an absolute axis.
80  // @param abs_type One of the |KEY_*| or |BTN_*| constants from
81  // <linux/input.h>.
82  int ConfigureAbs(uint16_t abs_type, int32_t min, int32_t max, int32_t fuzz,
83                   int32_t flat);
84
85  // Configure the number of multitouch slots.
86  int ConfigureAbsSlots(int slots);
87
88  // Configure multitouch coordinate range.
89  int ConfigureMultiTouchXY(int32_t x0, int32_t y0, int32_t x1, int32_t y1);
90
91  // Configure a relative axis.
92  // @param rel_type One of the |REL_*| constants from <linux/input.h>.
93  int ConfigureRel(uint16_t rel_type);
94
95  // Complete configuration and create the input device.
96  int ConfigureEnd();
97
98  // Send various events.
99  //
100  int Send(uint16_t type, uint16_t code, int32_t value);
101  int SendSynReport();
102  int SendKey(uint16_t code, int32_t value);
103  int SendAbs(uint16_t code, int32_t value);
104  int SendRel(uint16_t code, int32_t value);
105  int SendMultiTouchSlot(int32_t slot);
106  int SendMultiTouchXY(int32_t slot, int32_t id, int32_t x, int32_t y);
107  int SendMultiTouchLift(int32_t slot);
108
109  void dumpInternal(String8& result);
110
111 protected:
112  // Must be called only between construction and ConfigureBegin().
113  inline void SetUInputForTesting(UInput* uinput) { uinput_ = uinput; }
114  // Caller must not retain pointer longer than EvdevInjector.
115  inline const uinput_user_dev* GetUiDevForTesting() const { return &uidev_; }
116
117 private:
118  // Phase to enforce that configuration is complete before events are sent.
119  enum class State { NEW, CONFIGURING, READY, CLOSED };
120
121  // Sets |error_| if it is not already set; returns |code|.
122  int Error(int code);
123
124  // Returns a nonzero error if the injector is not in the required |state|.
125  int RequireState(State state);
126
127  // Configures an event type if necessary.
128  // @param type One of the |EV_*| constants from <linux/input.h>.
129  int EnableEventType(uint16_t type);
130
131  // Active pointer to owned or testing UInput.
132  UInput* uinput_ = nullptr;
133  std::unique_ptr<UInput> owned_uinput_;
134
135  State state_ = State::NEW;
136  int error_ = 0;
137  uinput_user_dev uidev_;
138  std::unordered_set<uint16_t> enabled_event_types_;
139  int32_t latest_slot_ = -1;
140
141  EvdevInjector(const EvdevInjector&) = delete;
142  void operator=(const EvdevInjector&) = delete;
143};
144
145}  // namespace dvr
146}  // namespace android
147
148#endif  // ANDROID_DVR_EVDEV_INJECTOR_H
149