Home | History | Annotate | Download | only in virtual_touchpad
      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   };
     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