• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
12 namespace android {
13 namespace dvr {
14 
15 // Simulated evdev input device.
16 //
17 class 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:
UInput()44     UInput() {}
~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 
EvdevInjector()56   EvdevInjector() {}
~EvdevInjector()57   ~EvdevInjector() { Close(); }
58   void Close();
59 
GetError()60   int GetError() const { return error_; }
ResetError()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().
SetUInputForTesting(UInput * uinput)113   inline void SetUInputForTesting(UInput* uinput) { uinput_ = uinput; }
114   // Caller must not retain pointer longer than EvdevInjector.
GetUiDevForTesting()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