inputflinger: Initial support for rotary encoders.

This change introduces support for rotary encoder input devices.

We also define a new input source (namely, AINPUT_SOURCE_ROTARY_ENCODER)
and a new axis of input (namely, AXIS_SCROLL), since the rotary encoder
motion doesn't necessarily tie to a horizontal or vertical scroll
motion.

A ROTARY_ENCODER input device class is also introduced, corresponding to
the new input source.

A new input source can be defined as producing rotary encoder motion
events, if its corresponding .idc file contains the following
declaration:

    device.type = rotaryEncoder

Bug: 18707397

Change-Id: I8ccd540908311d1ff44fdfeba81b691895413641
Signed-off-by: Prashant Malani <pmalani@google.com>
This commit is contained in:
Prashant Malani 2015-08-11 18:29:28 -07:00
parent 4baa69ddd2
commit ac72bbf4e4
5 changed files with 132 additions and 0 deletions

View File

@ -643,6 +643,13 @@ enum {
* against the surface.
*/
AMOTION_EVENT_AXIS_TILT = 25,
/**
* Axis constant: Generic scroll axis of a motion event.
*
* - This is used for scroll axis motion events that can't be classified as strictly
* vertical or horizontal. The movement of a rotating scroller is an example of this.
*/
AMOTION_EVENT_AXIS_SCROLL = 26,
/**
* Axis constant: Generic 1 axis of a motion event.
* The interpretation of a generic axis is device-specific.
@ -817,6 +824,8 @@ enum {
AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
/** joystick */
AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
/** rotary encoder */
AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
/** any */
AINPUT_SOURCE_ANY = 0xffffff00,

View File

@ -1177,6 +1177,15 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
device->classes |= INPUT_DEVICE_CLASS_CURSOR;
}
// See if this is a rotary encoder type device.
String8 deviceType = String8();
if (device->configuration &&
device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
if (!deviceType.compare(String8("rotaryEncoder"))) {
device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
}
}
// See if this is a touch pad.
// Is this a new modern multi-touch driver?
if (test_bit(ABS_MT_POSITION_X, device->absBitmask)

View File

@ -137,6 +137,9 @@ enum {
/* The input device is an external stylus (has data we want to fuse with touch data). */
INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
/* The input device has a rotary encoder */
INPUT_DEVICE_CLASS_ROTARY_ENCODER = 0x00001000,
/* The input device is virtual (not a real device, not part of UI configuration). */
INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,

View File

@ -450,6 +450,11 @@ InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controlle
device->addMapper(new SwitchInputMapper(device));
}
// Scroll wheel-like devices.
if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
device->addMapper(new RotaryEncoderInputMapper(device));
}
// Vibrator-like devices.
if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
device->addMapper(new VibratorInputMapper(device));
@ -2718,6 +2723,92 @@ void CursorInputMapper::fadePointer() {
}
}
// --- RotaryEncoderInputMapper ---
RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
InputMapper(device) {
mSource = AINPUT_SOURCE_ROTARY_ENCODER;
}
RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {
}
uint32_t RotaryEncoderInputMapper::getSources() {
return mSource;
}
void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
InputMapper::populateDeviceInfo(info);
if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
}
}
void RotaryEncoderInputMapper::dump(String8& dump) {
dump.append(INDENT2 "Rotary Encoder Input Mapper:\n");
dump.appendFormat(INDENT3 "HaveWheel: %s\n",
toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
}
void RotaryEncoderInputMapper::configure(nsecs_t when,
const InputReaderConfiguration* config, uint32_t changes) {
InputMapper::configure(when, config, changes);
if (!changes) {
mRotaryEncoderScrollAccumulator.configure(getDevice());
}
}
void RotaryEncoderInputMapper::reset(nsecs_t when) {
mRotaryEncoderScrollAccumulator.reset(getDevice());
InputMapper::reset(when);
}
void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
mRotaryEncoderScrollAccumulator.process(rawEvent);
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
sync(rawEvent->when);
}
}
void RotaryEncoderInputMapper::sync(nsecs_t when) {
PointerCoords pointerCoords;
pointerCoords.clear();
PointerProperties pointerProperties;
pointerProperties.clear();
pointerProperties.id = 0;
pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
bool scrolled = scroll != 0;
// This is not a pointer, so it's not associated with a display.
int32_t displayId = ADISPLAY_ID_NONE;
// Moving the rotary encoder should wake the device (if specified).
uint32_t policyFlags = 0;
if (scrolled && getDevice()->isExternal()) {
policyFlags |= POLICY_FLAG_WAKE;
}
// Send motion event.
if (scrolled) {
int32_t metaState = mContext->getGlobalMetaState();
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll);
NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0,
AMOTION_EVENT_EDGE_FLAG_NONE,
displayId, 1, &pointerProperties, &pointerCoords,
0, 0, 0);
getListener()->notifyMotion(&scrollArgs);
}
mRotaryEncoderScrollAccumulator.finishSync();
}
// --- TouchInputMapper ---

View File

@ -1232,6 +1232,26 @@ private:
};
class RotaryEncoderInputMapper : public InputMapper {
public:
RotaryEncoderInputMapper(InputDevice* device);
virtual ~RotaryEncoderInputMapper();
virtual uint32_t getSources();
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
virtual void reset(nsecs_t when);
virtual void process(const RawEvent* rawEvent);
private:
CursorScrollAccumulator mRotaryEncoderScrollAccumulator;
int32_t mSource;
void sync(nsecs_t when);
};
class TouchInputMapper : public InputMapper {
public:
TouchInputMapper(InputDevice* device);