EvdevInjector.h revision 4b64dd48b6896d6b963f0a3a0259d3d2a7076a9e
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  };
34
35  // Key event |value| is not defined in <linux/input.h>.
36  enum : int32_t { KEY_RELEASE = 0, KEY_PRESS = 1, KEY_REPEAT = 2 };
37
38  // UInput provides a shim to intercept /dev/uinput operations
39  // just above the system call level, for testing.
40  //
41  class UInput {
42   public:
43    UInput() {}
44    virtual ~UInput() {}
45    virtual int Open();
46    virtual int Close();
47    virtual int Write(const void* buf, size_t count);
48    virtual int IoctlVoid(int request);
49    virtual int IoctlSetInt(int request, int value);
50
51   private:
52    base::unique_fd fd_;
53  };
54
55  EvdevInjector() {}
56  ~EvdevInjector() { Close(); }
57  void Close();
58
59  int GetError() const { return error_; }
60  void ResetError() { error_ = 0; }
61
62  // Configuration must be performed before sending any events.
63  // |ConfigureBegin()| must be called first, and |ConfigureEnd()| last,
64  // with zero or more other |Configure...()| calls in between in any order.
65
66  // Configure the basic evdev device properties; must be called first.
67  int ConfigureBegin(const char* device_name, int16_t bustype, int16_t vendor,
68                     int16_t product, int16_t version);
69
70  // Configure an optional input device property.
71  // @param property  One of the |INPUT_PROP_*| constants from <linux/input.h>.
72  int ConfigureInputProperty(int property);
73
74  // Configure an input key.
75  // @param key One of the |KEY_*| or |BTN_*| constants from <linux/input.h>.
76  int ConfigureKey(uint16_t key);
77
78  // Configure an absolute axis.
79  // @param abs_type One of the |KEY_*| or |BTN_*| constants from
80  // <linux/input.h>.
81  int ConfigureAbs(uint16_t abs_type, int32_t min, int32_t max, int32_t fuzz,
82                   int32_t flat);
83
84  // Configure the number of multitouch slots.
85  int ConfigureAbsSlots(int slots);
86
87  // Configure multitouch coordinate range.
88  int ConfigureMultiTouchXY(int32_t x0, int32_t y0, int32_t x1, int32_t y1);
89
90  // Complete configuration and create the input device.
91  int ConfigureEnd();
92
93  // Send various events.
94  //
95  int Send(uint16_t type, uint16_t code, int32_t value);
96  int SendSynReport();
97  int SendKey(uint16_t code, int32_t value);
98  int SendAbs(uint16_t code, int32_t value);
99  int SendMultiTouchSlot(int32_t slot);
100  int SendMultiTouchXY(int32_t slot, int32_t id, int32_t x, int32_t y);
101  int SendMultiTouchLift(int32_t slot);
102
103  void dumpInternal(String8& result);
104
105 protected:
106  // Must be called only between construction and ConfigureBegin().
107  inline void SetUInputForTesting(UInput* uinput) { uinput_ = uinput; }
108  // Caller must not retain pointer longer than EvdevInjector.
109  inline const uinput_user_dev* GetUiDevForTesting() const { return &uidev_; }
110
111 private:
112  // Phase to enforce that configuration is complete before events are sent.
113  enum class State { NEW, CONFIGURING, READY, CLOSED };
114
115  // Sets |error_| if it is not already set; returns |code|.
116  int Error(int code);
117
118  // Returns a nonzero error if the injector is not in the required |state|.
119  int RequireState(State state);
120
121  // Configures an event type if necessary.
122  // @param type One of the |EV_*| constants from <linux/input.h>.
123  int EnableEventType(uint16_t type);
124
125  // Active pointer to owned or testing UInput.
126  UInput* uinput_ = nullptr;
127  std::unique_ptr<UInput> owned_uinput_;
128
129  State state_ = State::NEW;
130  int error_ = 0;
131  uinput_user_dev uidev_;
132  std::unordered_set<uint16_t> enabled_event_types_;
133  int32_t latest_slot_ = -1;
134
135  EvdevInjector(const EvdevInjector&) = delete;
136  void operator=(const EvdevInjector&) = delete;
137};
138
139}  // namespace dvr
140}  // namespace android
141
142#endif  // ANDROID_DVR_EVDEV_INJECTOR_H
143