Merge "Fix some input device mapping bugs with certain drivers." into gingerbread

This commit is contained in:
Jeff Brown
2010-08-18 13:38:32 -07:00
committed by Android (Google) Code Review
2 changed files with 98 additions and 84 deletions

View File

@@ -480,10 +480,6 @@ private:
inline void clear() { inline void clear() {
fields = 0; fields = 0;
} }
inline bool isDirty() {
return fields != 0;
}
} mAccumulator; } mAccumulator;
float mXScale; float mXScale;
@@ -702,7 +698,7 @@ private:
} historyData[AVERAGING_HISTORY_SIZE]; } historyData[AVERAGING_HISTORY_SIZE];
} mAveragingTouchFilter; } mAveragingTouchFilter;
struct JumpTouchFilterState { struct JumpyTouchFilterState {
uint32_t jumpyPointsDropped; uint32_t jumpyPointsDropped;
} mJumpyTouchFilter; } mJumpyTouchFilter;
@@ -765,10 +761,6 @@ private:
inline void clear() { inline void clear() {
fields = 0; fields = 0;
} }
inline bool isDirty() {
return fields != 0;
}
} mAccumulator; } mAccumulator;
bool mDown; bool mDown;
@@ -804,7 +796,8 @@ private:
FIELD_ABS_MT_WIDTH_MAJOR = 16, FIELD_ABS_MT_WIDTH_MAJOR = 16,
FIELD_ABS_MT_WIDTH_MINOR = 32, FIELD_ABS_MT_WIDTH_MINOR = 32,
FIELD_ABS_MT_ORIENTATION = 64, FIELD_ABS_MT_ORIENTATION = 64,
FIELD_ABS_MT_TRACKING_ID = 128 FIELD_ABS_MT_TRACKING_ID = 128,
FIELD_ABS_MT_PRESSURE = 256,
}; };
uint32_t pointerCount; uint32_t pointerCount;
@@ -819,6 +812,7 @@ private:
int32_t absMTWidthMinor; int32_t absMTWidthMinor;
int32_t absMTOrientation; int32_t absMTOrientation;
int32_t absMTTrackingId; int32_t absMTTrackingId;
int32_t absMTPressure;
inline void clear() { inline void clear() {
fields = 0; fields = 0;
@@ -829,10 +823,6 @@ private:
pointerCount = 0; pointerCount = 0;
pointers[0].clear(); pointers[0].clear();
} }
inline bool isDirty() {
return pointerCount != 0;
}
} mAccumulator; } mAccumulator;
void initialize(); void initialize();

View File

@@ -945,7 +945,6 @@ void TrackballInputMapper::reset() {
mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE; mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
mAccumulator.btnMouse = false; mAccumulator.btnMouse = false;
sync(when); sync(when);
mAccumulator.clear();
} }
InputMapper::reset(); InputMapper::reset();
@@ -958,9 +957,9 @@ void TrackballInputMapper::process(const RawEvent* rawEvent) {
case BTN_MOUSE: case BTN_MOUSE:
mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE; mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
mAccumulator.btnMouse = rawEvent->value != 0; mAccumulator.btnMouse = rawEvent->value != 0;
// Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
// we need to ensure that we report the up/down promptly.
sync(rawEvent->when); sync(rawEvent->when);
mAccumulator.clear();
break; break;
} }
break; break;
@@ -981,10 +980,7 @@ void TrackballInputMapper::process(const RawEvent* rawEvent) {
case EV_SYN: case EV_SYN:
switch (rawEvent->scanCode) { switch (rawEvent->scanCode) {
case SYN_REPORT: case SYN_REPORT:
if (mAccumulator.isDirty()) { sync(rawEvent->when);
sync(rawEvent->when);
mAccumulator.clear();
}
break; break;
} }
break; break;
@@ -992,13 +988,17 @@ void TrackballInputMapper::process(const RawEvent* rawEvent) {
} }
void TrackballInputMapper::sync(nsecs_t when) { void TrackballInputMapper::sync(nsecs_t when) {
uint32_t fields = mAccumulator.fields;
if (fields == 0) {
return; // no new state changes, so nothing to do
}
int motionEventAction; int motionEventAction;
PointerCoords pointerCoords; PointerCoords pointerCoords;
nsecs_t downTime; nsecs_t downTime;
{ // acquire lock { // acquire lock
AutoMutex _l(mLock); AutoMutex _l(mLock);
uint32_t fields = mAccumulator.fields;
bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE; bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
if (downChanged) { if (downChanged) {
@@ -1061,6 +1061,8 @@ void TrackballInputMapper::sync(nsecs_t when) {
} // release lock } // release lock
applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime); applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
mAccumulator.clear();
} }
void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction, void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
@@ -2380,8 +2382,8 @@ void SingleTouchInputMapper::initialize() {
mDown = false; mDown = false;
mX = 0; mX = 0;
mY = 0; mY = 0;
mPressure = 0; mPressure = 1; // default to 1 for devices that don't report pressure
mSize = 0; mSize = 0; // default to 0 for devices that don't report size
} }
void SingleTouchInputMapper::reset() { void SingleTouchInputMapper::reset() {
@@ -2397,9 +2399,9 @@ void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
case BTN_TOUCH: case BTN_TOUCH:
mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH; mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
mAccumulator.btnTouch = rawEvent->value != 0; mAccumulator.btnTouch = rawEvent->value != 0;
// Don't sync immediately. Wait until the next SYN_REPORT since we might
sync(rawEvent->when); // not have received valid position information yet. This logic assumes that
mAccumulator.clear(); // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
break; break;
} }
break; break;
@@ -2428,10 +2430,7 @@ void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
case EV_SYN: case EV_SYN:
switch (rawEvent->scanCode) { switch (rawEvent->scanCode) {
case SYN_REPORT: case SYN_REPORT:
if (mAccumulator.isDirty()) { sync(rawEvent->when);
sync(rawEvent->when);
mAccumulator.clear();
}
break; break;
} }
break; break;
@@ -2439,9 +2438,10 @@ void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
} }
void SingleTouchInputMapper::sync(nsecs_t when) { void SingleTouchInputMapper::sync(nsecs_t when) {
/* Update device state */
uint32_t fields = mAccumulator.fields; uint32_t fields = mAccumulator.fields;
if (fields == 0) {
return; // no new state changes, so nothing to do
}
if (fields & Accumulator::FIELD_BTN_TOUCH) { if (fields & Accumulator::FIELD_BTN_TOUCH) {
mDown = mAccumulator.btnTouch; mDown = mAccumulator.btnTouch;
@@ -2472,8 +2472,8 @@ void SingleTouchInputMapper::sync(nsecs_t when) {
mCurrentTouch.pointers[0].y = mY; mCurrentTouch.pointers[0].y = mY;
mCurrentTouch.pointers[0].pressure = mPressure; mCurrentTouch.pointers[0].pressure = mPressure;
mCurrentTouch.pointers[0].size = mSize; mCurrentTouch.pointers[0].size = mSize;
mCurrentTouch.pointers[0].touchMajor = mPressure; mCurrentTouch.pointers[0].touchMajor = mSize;
mCurrentTouch.pointers[0].touchMinor = mPressure; mCurrentTouch.pointers[0].touchMinor = mSize;
mCurrentTouch.pointers[0].toolMajor = mSize; mCurrentTouch.pointers[0].toolMajor = mSize;
mCurrentTouch.pointers[0].toolMinor = mSize; mCurrentTouch.pointers[0].toolMinor = mSize;
mCurrentTouch.pointers[0].orientation = 0; mCurrentTouch.pointers[0].orientation = 0;
@@ -2482,6 +2482,8 @@ void SingleTouchInputMapper::sync(nsecs_t when) {
} }
syncTouch(when, true); syncTouch(when, true);
mAccumulator.clear();
} }
void SingleTouchInputMapper::configureAxes() { void SingleTouchInputMapper::configureAxes() {
@@ -2494,8 +2496,8 @@ void SingleTouchInputMapper::configureAxes() {
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mAxes.pressure); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mAxes.pressure);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mAxes.size); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mAxes.size);
mAxes.touchMajor = mAxes.pressure; mAxes.touchMajor = mAxes.size;
mAxes.touchMinor = mAxes.pressure; mAxes.touchMinor = mAxes.size;
mAxes.toolMajor = mAxes.size; mAxes.toolMajor = mAxes.size;
mAxes.toolMinor = mAxes.size; mAxes.toolMinor = mAxes.size;
} }
@@ -2585,10 +2587,7 @@ void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
} }
case SYN_REPORT: case SYN_REPORT:
if (mAccumulator.isDirty()) { sync(rawEvent->when);
sync(rawEvent->when);
mAccumulator.clear();
}
break; break;
} }
break; break;
@@ -2598,11 +2597,7 @@ void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
void MultiTouchInputMapper::sync(nsecs_t when) { void MultiTouchInputMapper::sync(nsecs_t when) {
static const uint32_t REQUIRED_FIELDS = static const uint32_t REQUIRED_FIELDS =
Accumulator::FIELD_ABS_MT_POSITION_X Accumulator::FIELD_ABS_MT_POSITION_X
| Accumulator::FIELD_ABS_MT_POSITION_Y | Accumulator::FIELD_ABS_MT_POSITION_Y;
| Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
| Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
/* Update device state */
uint32_t inCount = mAccumulator.pointerCount; uint32_t inCount = mAccumulator.pointerCount;
uint32_t outCount = 0; uint32_t outCount = 0;
@@ -2611,53 +2606,76 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
mCurrentTouch.clear(); mCurrentTouch.clear();
for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) { for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
uint32_t fields = mAccumulator.pointers[inIndex].fields; const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
uint32_t fields = inPointer.fields;
if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) { if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
#if DEBUG_POINTERS // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d", // Drop this finger.
inIndex, fields);
continue;
#endif
}
if (mAccumulator.pointers[inIndex].absMTTouchMajor <= 0) {
// Pointer is not down. Drop it.
continue; continue;
} }
mCurrentTouch.pointers[outCount].x = mAccumulator.pointers[inIndex].absMTPositionX; PointerData& outPointer = mCurrentTouch.pointers[outCount];
mCurrentTouch.pointers[outCount].y = mAccumulator.pointers[inIndex].absMTPositionY; outPointer.x = inPointer.absMTPositionX;
outPointer.y = inPointer.absMTPositionY;
mCurrentTouch.pointers[outCount].touchMajor = if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
mAccumulator.pointers[inIndex].absMTTouchMajor; int32_t value = inPointer.absMTTouchMajor;
mCurrentTouch.pointers[outCount].touchMinor = if (value <= 0) {
(fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) != 0 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
? mAccumulator.pointers[inIndex].absMTTouchMinor // a pointer up. Drop this finger.
: mAccumulator.pointers[inIndex].absMTTouchMajor; continue;
}
outPointer.touchMajor = inPointer.absMTTouchMajor;
} else {
outPointer.touchMajor = 0;
}
mCurrentTouch.pointers[outCount].toolMajor = if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
mAccumulator.pointers[inIndex].absMTWidthMajor; outPointer.touchMinor = inPointer.absMTTouchMinor;
mCurrentTouch.pointers[outCount].toolMinor = } else {
(fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) != 0 outPointer.touchMinor = outPointer.touchMajor;
? mAccumulator.pointers[inIndex].absMTWidthMinor }
: mAccumulator.pointers[inIndex].absMTWidthMajor;
mCurrentTouch.pointers[outCount].orientation = if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
(fields & Accumulator::FIELD_ABS_MT_ORIENTATION) != 0 outPointer.toolMajor = inPointer.absMTWidthMajor;
? mAccumulator.pointers[inIndex].absMTOrientation : 0; } else {
outPointer.toolMajor = outPointer.touchMajor;
}
// Derive an approximation of pressure and size. if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
// FIXME assignment of pressure may be incorrect, probably better to let outPointer.toolMinor = inPointer.absMTWidthMinor;
// pressure = touch / width. Later on we pass width to MotionEvent as a size, which } else {
// isn't quite right either. Should be using touch for that. outPointer.toolMinor = outPointer.toolMajor;
mCurrentTouch.pointers[outCount].pressure = mAccumulator.pointers[inIndex].absMTTouchMajor; }
mCurrentTouch.pointers[outCount].size = mAccumulator.pointers[inIndex].absMTWidthMajor;
if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
outPointer.orientation = inPointer.absMTOrientation;
} else {
outPointer.orientation = 0;
}
if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
outPointer.pressure = inPointer.absMTPressure;
} else {
// Derive an approximation of pressure.
// FIXME Traditionally we have just passed a normalized value based on
// ABS_MT_TOUCH_MAJOR as an estimate of pressure but the result is not
// very meaningful, particularly on large displays. We should probably let
// pressure = touch_major / tool_major but it is unclear whether that will
// break applications.
outPointer.pressure = outPointer.touchMajor;
}
// Size is an alias for a normalized tool width.
// FIXME Normalized tool width doesn't actually make much sense since it literally
// means the approaching contact major axis is divided by its full range as
// reported by the driver. On a large display this could produce very small values.
outPointer.size = outPointer.toolMajor;
if (havePointerIds) { if (havePointerIds) {
if (fields & Accumulator:: if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
FIELD_ABS_MT_TRACKING_ID) { uint32_t id = uint32_t(inPointer.absMTTrackingId);
uint32_t id = uint32_t(mAccumulator.pointers[inIndex].absMTTrackingId);
if (id > MAX_POINTER_ID) { if (id > MAX_POINTER_ID) {
#if DEBUG_POINTERS #if DEBUG_POINTERS
@@ -2668,7 +2686,7 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
havePointerIds = false; havePointerIds = false;
} }
else { else {
mCurrentTouch.pointers[outCount].id = id; outPointer.id = id;
mCurrentTouch.idToIndex[id] = outCount; mCurrentTouch.idToIndex[id] = outCount;
mCurrentTouch.idBits.markBit(id); mCurrentTouch.idBits.markBit(id);
} }
@@ -2683,6 +2701,8 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
mCurrentTouch.pointerCount = outCount; mCurrentTouch.pointerCount = outCount;
syncTouch(when, havePointerIds); syncTouch(when, havePointerIds);
mAccumulator.clear();
} }
void MultiTouchInputMapper::configureAxes() { void MultiTouchInputMapper::configureAxes() {
@@ -2697,6 +2717,7 @@ void MultiTouchInputMapper::configureAxes() {
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mAxes.toolMajor); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mAxes.toolMajor);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mAxes.toolMinor); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mAxes.toolMinor);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mAxes.orientation); getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mAxes.orientation);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mAxes.pressure);
if (! mAxes.touchMinor.valid) { if (! mAxes.touchMinor.valid) {
mAxes.touchMinor = mAxes.touchMajor; mAxes.touchMinor = mAxes.touchMajor;
@@ -2706,7 +2727,10 @@ void MultiTouchInputMapper::configureAxes() {
mAxes.toolMinor = mAxes.toolMajor; mAxes.toolMinor = mAxes.toolMajor;
} }
mAxes.pressure = mAxes.touchMajor; if (! mAxes.pressure.valid) {
mAxes.pressure = mAxes.touchMajor;
}
mAxes.size = mAxes.toolMajor; mAxes.size = mAxes.toolMajor;
} }