#ifndef ANDROID_DVR_EVDEV_INJECTOR_H #define ANDROID_DVR_EVDEV_INJECTOR_H #include #include #include #include #include #include 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 . 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 . int ConfigureInputProperty(int property); // Configure an input key. // @param key One of the |KEY_*| or |BTN_*| constants from . int ConfigureKey(uint16_t key); // Configure an absolute axis. // @param abs_type One of the |KEY_*| or |BTN_*| constants from // . 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 . 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 . int EnableEventType(uint16_t type); // Active pointer to owned or testing UInput. UInput* uinput_ = nullptr; std::unique_ptr owned_uinput_; State state_ = State::NEW; int error_ = 0; uinput_user_dev uidev_; std::unordered_set 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