1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
#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
|