| #ifndef ANDROID_DVR_EVDEV_INJECTOR_H |
| #define ANDROID_DVR_EVDEV_INJECTOR_H |
| |
| #include <android-base/unique_fd.h> |
| #include <linux/uinput.h> |
| #include <utils/String8.h> |
| |
| #include <cstdint> |
| #include <memory> |
| #include <unordered_set> |
| |
| namespace android { |
| namespace dvr { |
| |
| // Simulated evdev input device. |
| // |
| class EvdevInjector { |
| public: |
| // EvdevInjector-specific error codes are negative integers; other non-zero |
| // values returned from public routines are |errno| codes from underlying I/O. |
| // EvdevInjector maintains a 'sticky' error state, similar to |errno|, so that |
| // a caller can perform a sequence of operations and check for errors at the |
| // end using |GetError()|. In general, the first such error will be recorded |
| // and will suppress effects of further device operations until |ResetError()| |
| // is called. |
| // |
| enum : int { |
| ERROR_DEVICE_NAME = -1, // Invalid device name. |
| ERROR_PROPERTY_RANGE = -2, // |INPUT_PROP_*| code out of range. |
| ERROR_KEY_RANGE = -3, // |KEY_*|/|BTN_*| code out of range. |
| ERROR_ABS_RANGE = -4, // |ABS_*| code out of range. |
| ERROR_SEQUENCING = -5, // Configure/Send out of order. |
| ERROR_REL_RANGE = -6, // |REL_*| code out of range. |
| }; |
| |
| // Key event |value| is not defined in <linux/input.h>. |
| enum : int32_t { KEY_RELEASE = 0, KEY_PRESS = 1, KEY_REPEAT = 2 }; |
| |
| // UInput provides a shim to intercept /dev/uinput operations |
| // just above the system call level, for testing. |
| // |
| class UInput { |
| public: |
| UInput() {} |
| virtual ~UInput() {} |
| virtual int Open(); |
| virtual int Close(); |
| virtual int Write(const void* buf, size_t count); |
| virtual int IoctlVoid(int request); |
| virtual int IoctlSetInt(int request, int value); |
| |
| private: |
| base::unique_fd fd_; |
| }; |
| |
| EvdevInjector() {} |
| ~EvdevInjector() { Close(); } |
| void Close(); |
| |
| int GetError() const { return error_; } |
| void ResetError() { error_ = 0; } |
| |
| // Configuration must be performed before sending any events. |
| // |ConfigureBegin()| must be called first, and |ConfigureEnd()| last, |
| // with zero or more other |Configure...()| calls in between in any order. |
| |
| // Configure the basic evdev device properties; must be called first. |
| int ConfigureBegin(const char* device_name, int16_t bustype, int16_t vendor, |
| int16_t product, int16_t version); |
| |
| // Configure an optional input device property. |
| // @param property One of the |INPUT_PROP_*| constants from <linux/input.h>. |
| int ConfigureInputProperty(int property); |
| |
| // Configure an input key. |
| // @param key One of the |KEY_*| or |BTN_*| constants from <linux/input.h>. |
| int ConfigureKey(uint16_t key); |
| |
| // Configure an absolute axis. |
| // @param abs_type One of the |KEY_*| or |BTN_*| constants from |
| // <linux/input.h>. |
| int ConfigureAbs(uint16_t abs_type, int32_t min, int32_t max, int32_t fuzz, |
| int32_t flat); |
| |
| // Configure the number of multitouch slots. |
| int ConfigureAbsSlots(int slots); |
| |
| // Configure multitouch coordinate range. |
| int ConfigureMultiTouchXY(int32_t x0, int32_t y0, int32_t x1, int32_t y1); |
| |
| // Configure a relative axis. |
| // @param rel_type One of the |REL_*| constants from <linux/input.h>. |
| int ConfigureRel(uint16_t rel_type); |
| |
| // Complete configuration and create the input device. |
| int ConfigureEnd(); |
| |
| // Send various events. |
| // |
| int Send(uint16_t type, uint16_t code, int32_t value); |
| int SendSynReport(); |
| int SendKey(uint16_t code, int32_t value); |
| int SendAbs(uint16_t code, int32_t value); |
| int SendRel(uint16_t code, int32_t value); |
| int SendMultiTouchSlot(int32_t slot); |
| int SendMultiTouchXY(int32_t slot, int32_t id, int32_t x, int32_t y); |
| int SendMultiTouchLift(int32_t slot); |
| |
| void dumpInternal(String8& result); |
| |
| protected: |
| // Must be called only between construction and ConfigureBegin(). |
| inline void SetUInputForTesting(UInput* uinput) { uinput_ = uinput; } |
| // Caller must not retain pointer longer than EvdevInjector. |
| inline const uinput_user_dev* GetUiDevForTesting() const { return &uidev_; } |
| |
| private: |
| // Phase to enforce that configuration is complete before events are sent. |
| enum class State { NEW, CONFIGURING, READY, CLOSED }; |
| |
| // Sets |error_| if it is not already set; returns |code|. |
| int Error(int code); |
| |
| // Returns a nonzero error if the injector is not in the required |state|. |
| int RequireState(State state); |
| |
| // Configures an event type if necessary. |
| // @param type One of the |EV_*| constants from <linux/input.h>. |
| int EnableEventType(uint16_t type); |
| |
| // Active pointer to owned or testing UInput. |
| UInput* uinput_ = nullptr; |
| std::unique_ptr<UInput> owned_uinput_; |
| |
| State state_ = State::NEW; |
| int error_ = 0; |
| uinput_user_dev uidev_; |
| std::unordered_set<uint16_t> enabled_event_types_; |
| int32_t latest_slot_ = -1; |
| |
| EvdevInjector(const EvdevInjector&) = delete; |
| void operator=(const EvdevInjector&) = delete; |
| }; |
| |
| } // namespace dvr |
| } // namespace android |
| |
| #endif // ANDROID_DVR_EVDEV_INJECTOR_H |