diff options
Diffstat (limited to 'libs/ui/InputReader.cpp')
-rw-r--r-- | libs/ui/InputReader.cpp | 1046 |
1 files changed, 810 insertions, 236 deletions
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp index 6f042ec7e8e4..8ffb48debe8f 100644 --- a/libs/ui/InputReader.cpp +++ b/libs/ui/InputReader.cpp @@ -26,11 +26,14 @@ #include <ui/InputReader.h> #include <stddef.h> +#include <stdlib.h> #include <unistd.h> #include <errno.h> #include <limits.h> #include <math.h> +#define INDENT " " + namespace android { // --- Static Functions --- @@ -52,6 +55,14 @@ inline static void swap(T& a, T& b) { b = temp; } +inline static float avg(float x, float y) { + return (x + y) / 2; +} + +inline static float pythag(float x, float y) { + return sqrtf(x * x + y * y); +} + int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) { int32_t mask; @@ -116,6 +127,64 @@ static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) { } +// --- InputDeviceCalibration --- + +InputDeviceCalibration::InputDeviceCalibration() { +} + +void InputDeviceCalibration::clear() { + mProperties.clear(); +} + +void InputDeviceCalibration::addProperty(const String8& key, const String8& value) { + mProperties.add(key, value); +} + +bool InputDeviceCalibration::tryGetProperty(const String8& key, String8& outValue) const { + ssize_t index = mProperties.indexOfKey(key); + if (index < 0) { + return false; + } + + outValue = mProperties.valueAt(index); + return true; +} + +bool InputDeviceCalibration::tryGetProperty(const String8& key, int32_t& outValue) const { + String8 stringValue; + if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) { + return false; + } + + char* end; + int value = strtol(stringValue.string(), & end, 10); + if (*end != '\0') { + LOGW("Input device calibration key '%s' has invalid value '%s'. Expected an integer.", + key.string(), stringValue.string()); + return false; + } + outValue = value; + return true; +} + +bool InputDeviceCalibration::tryGetProperty(const String8& key, float& outValue) const { + String8 stringValue; + if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) { + return false; + } + + char* end; + float value = strtof(stringValue.string(), & end); + if (*end != '\0') { + LOGW("Input device calibration key '%s' has invalid value '%s'. Expected a float.", + key.string(), stringValue.string()); + return false; + } + outValue = value; + return true; +} + + // --- InputReader --- InputReader::InputReader(const sp<EventHubInterface>& eventHub, @@ -167,9 +236,18 @@ void InputReader::addDevice(nsecs_t when, int32_t deviceId) { String8 name = mEventHub->getDeviceName(deviceId); uint32_t classes = mEventHub->getDeviceClasses(deviceId); + // Write a log message about the added device as a heading for subsequent log messages. + LOGI("Device added: id=0x%x, name=%s", deviceId, name.string()); + InputDevice* device = createDevice(deviceId, name, classes); device->configure(); + if (device->isIgnored()) { + LOGI(INDENT "Sources: none (device is ignored)"); + } else { + LOGI(INDENT "Sources: 0x%08x", device->getSources()); + } + bool added = false; { // acquire device registry writer lock RWLock::AutoWLock _wl(mDeviceRegistryLock); @@ -187,14 +265,6 @@ void InputReader::addDevice(nsecs_t when, int32_t deviceId) { return; } - if (device->isIgnored()) { - LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", - deviceId, name.string()); - } else { - LOGI("Device added: id=0x%x, name=%s, sources=%08x", - deviceId, name.string(), device->getSources()); - } - handleConfigurationChanged(when); } @@ -217,8 +287,7 @@ void InputReader::removeDevice(nsecs_t when, int32_t deviceId) { return; } - device->reset(); - + // Write a log message about the removed device as a heading for subsequent log messages. if (device->isIgnored()) { LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)", device->getId(), device->getName().string()); @@ -227,6 +296,8 @@ void InputReader::removeDevice(nsecs_t when, int32_t deviceId) { device->getId(), device->getName().string(), device->getSources()); } + device->reset(); + delete device; handleConfigurationChanged(when); @@ -537,6 +608,10 @@ void InputDevice::addMapper(InputMapper* mapper) { } void InputDevice::configure() { + if (! isIgnored()) { + mContext->getPolicy()->getInputDeviceCalibration(mName, mCalibration); + } + mSources = 0; size_t numMappers = mMappers.size(); @@ -1121,13 +1196,35 @@ void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x); info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y); - info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, mLocked.orientedRanges.pressure); - info->addMotionRange(AINPUT_MOTION_RANGE_SIZE, mLocked.orientedRanges.size); - info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR, mLocked.orientedRanges.touchMajor); - info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR, mLocked.orientedRanges.touchMinor); - info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR, mLocked.orientedRanges.toolMajor); - info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR, mLocked.orientedRanges.toolMinor); - info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION, mLocked.orientedRanges.orientation); + + if (mLocked.orientedRanges.havePressure) { + info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, + mLocked.orientedRanges.pressure); + } + + if (mLocked.orientedRanges.haveSize) { + info->addMotionRange(AINPUT_MOTION_RANGE_SIZE, + mLocked.orientedRanges.size); + } + + if (mLocked.orientedRanges.haveTouchArea) { + info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR, + mLocked.orientedRanges.touchMajor); + info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR, + mLocked.orientedRanges.touchMinor); + } + + if (mLocked.orientedRanges.haveToolArea) { + info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR, + mLocked.orientedRanges.toolMajor); + info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR, + mLocked.orientedRanges.toolMinor); + } + + if (mLocked.orientedRanges.haveOrientation) { + info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION, + mLocked.orientedRanges.orientation); + } } // release lock } @@ -1144,77 +1241,72 @@ void TouchInputMapper::initializeLocked() { mJumpyTouchFilter.jumpyPointsDropped = 0; mLocked.currentVirtualKey.down = false; + + mLocked.orientedRanges.havePressure = false; + mLocked.orientedRanges.haveSize = false; + mLocked.orientedRanges.haveTouchArea = false; + mLocked.orientedRanges.haveToolArea = false; + mLocked.orientedRanges.haveOrientation = false; +} + +static void logAxisInfo(RawAbsoluteAxisInfo axis, const char* name) { + if (axis.valid) { + LOGI(INDENT "Raw %s axis: min=%d, max=%d, flat=%d, fuzz=%d", + name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz); + } else { + LOGI(INDENT "Raw %s axis: unknown range", name); + } } void TouchInputMapper::configure() { InputMapper::configure(); // Configure basic parameters. - mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents(); - mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents(); - mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents(); + configureParameters(); // Configure absolute axis information. - configureAxes(); + configureRawAxes(); + logRawAxes(); + + // Prepare input device calibration. + parseCalibration(); + resolveCalibration(); + logCalibration(); { // acquire lock AutoMutex _l(mLock); - // Configure pressure factors. - if (mAxes.pressure.valid) { - mLocked.pressureOrigin = mAxes.pressure.minValue; - mLocked.pressureScale = 1.0f / mAxes.pressure.getRange(); - } else { - mLocked.pressureOrigin = 0; - mLocked.pressureScale = 1.0f; - } - - mLocked.orientedRanges.pressure.min = 0.0f; - mLocked.orientedRanges.pressure.max = 1.0f; - mLocked.orientedRanges.pressure.flat = 0.0f; - mLocked.orientedRanges.pressure.fuzz = mLocked.pressureScale; - - // Configure size factors. - if (mAxes.size.valid) { - mLocked.sizeOrigin = mAxes.size.minValue; - mLocked.sizeScale = 1.0f / mAxes.size.getRange(); - } else { - mLocked.sizeOrigin = 0; - mLocked.sizeScale = 1.0f; - } - - mLocked.orientedRanges.size.min = 0.0f; - mLocked.orientedRanges.size.max = 1.0f; - mLocked.orientedRanges.size.flat = 0.0f; - mLocked.orientedRanges.size.fuzz = mLocked.sizeScale; - - // Configure orientation factors. - if (mAxes.orientation.valid && mAxes.orientation.maxValue > 0) { - mLocked.orientationScale = float(M_PI_2) / mAxes.orientation.maxValue; - } else { - mLocked.orientationScale = 0.0f; - } - - mLocked.orientedRanges.orientation.min = - M_PI_2; - mLocked.orientedRanges.orientation.max = M_PI_2; - mLocked.orientedRanges.orientation.flat = 0; - mLocked.orientedRanges.orientation.fuzz = mLocked.orientationScale; - - // Configure surface dimensions and orientation. + // Configure surface dimensions and orientation. configureSurfaceLocked(); } // release lock } -void TouchInputMapper::configureAxes() { - mAxes.x.valid = false; - mAxes.y.valid = false; - mAxes.pressure.valid = false; - mAxes.size.valid = false; - mAxes.touchMajor.valid = false; - mAxes.touchMinor.valid = false; - mAxes.toolMajor.valid = false; - mAxes.toolMinor.valid = false; - mAxes.orientation.valid = false; +void TouchInputMapper::configureParameters() { + mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents(); + mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents(); + mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents(); +} + +void TouchInputMapper::configureRawAxes() { + mRawAxes.x.clear(); + mRawAxes.y.clear(); + mRawAxes.pressure.clear(); + mRawAxes.touchMajor.clear(); + mRawAxes.touchMinor.clear(); + mRawAxes.toolMajor.clear(); + mRawAxes.toolMinor.clear(); + mRawAxes.orientation.clear(); +} + +void TouchInputMapper::logRawAxes() { + logAxisInfo(mRawAxes.x, "x"); + logAxisInfo(mRawAxes.y, "y"); + logAxisInfo(mRawAxes.pressure, "pressure"); + logAxisInfo(mRawAxes.touchMajor, "touchMajor"); + logAxisInfo(mRawAxes.touchMinor, "touchMinor"); + logAxisInfo(mRawAxes.toolMajor, "toolMajor"); + logAxisInfo(mRawAxes.toolMinor, "toolMinor"); + logAxisInfo(mRawAxes.orientation, "orientation"); } bool TouchInputMapper::configureSurfaceLocked() { @@ -1228,8 +1320,8 @@ bool TouchInputMapper::configureSurfaceLocked() { } } else { orientation = InputReaderPolicyInterface::ROTATION_0; - width = mAxes.x.getRange(); - height = mAxes.y.getRange(); + width = mRawAxes.x.getRange(); + height = mRawAxes.y.getRange(); } bool orientationChanged = mLocked.surfaceOrientation != orientation; @@ -1239,24 +1331,24 @@ bool TouchInputMapper::configureSurfaceLocked() { bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height; if (sizeChanged) { + LOGI("Device configured: id=0x%x, name=%s (display size was changed)", + getDeviceId(), getDeviceName().string()); + mLocked.surfaceWidth = width; mLocked.surfaceHeight = height; - // Compute size-dependent translation and scaling factors and place virtual keys. - if (mAxes.x.valid && mAxes.y.valid) { - mLocked.xOrigin = mAxes.x.minValue; - mLocked.yOrigin = mAxes.y.minValue; - - LOGI("Device configured: id=0x%x, name=%s (display size was changed)", - getDeviceId(), getDeviceName().string()); - - mLocked.xScale = float(width) / mAxes.x.getRange(); - mLocked.yScale = float(height) / mAxes.y.getRange(); + // Configure X and Y factors. + if (mRawAxes.x.valid && mRawAxes.y.valid) { + mLocked.xOrigin = mRawAxes.x.minValue; + mLocked.yOrigin = mRawAxes.y.minValue; + mLocked.xScale = float(width) / mRawAxes.x.getRange(); + mLocked.yScale = float(height) / mRawAxes.y.getRange(); mLocked.xPrecision = 1.0f / mLocked.xScale; mLocked.yPrecision = 1.0f / mLocked.yScale; configureVirtualKeysLocked(); } else { + LOGW(INDENT "Touch device did not report support for X or Y axis!"); mLocked.xOrigin = 0; mLocked.yOrigin = 0; mLocked.xScale = 1.0f; @@ -1265,22 +1357,112 @@ bool TouchInputMapper::configureSurfaceLocked() { mLocked.yPrecision = 1.0f; } - // Configure touch and tool area ranges. - float diagonal = sqrt(float(width * width + height * height)); - float diagonalFuzz = sqrt(mLocked.xScale * mLocked.xScale - + mLocked.yScale * mLocked.yScale); + // Scale factor for terms that are not oriented in a particular axis. + // If the pixels are square then xScale == yScale otherwise we fake it + // by choosing an average. + mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale); + + // Size of diagonal axis. + float diagonalSize = pythag(width, height); + + // TouchMajor and TouchMinor factors. + if (mCalibration.touchAreaCalibration != Calibration::TOUCH_AREA_CALIBRATION_NONE) { + mLocked.orientedRanges.haveTouchArea = true; + mLocked.orientedRanges.touchMajor.min = 0; + mLocked.orientedRanges.touchMajor.max = diagonalSize; + mLocked.orientedRanges.touchMajor.flat = 0; + mLocked.orientedRanges.touchMajor.fuzz = 0; + mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor; + } + + // ToolMajor and ToolMinor factors. + if (mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) { + mLocked.toolAreaLinearScale = 0; + mLocked.toolAreaLinearBias = 0; + if (mCalibration.toolAreaCalibration == Calibration::TOOL_AREA_CALIBRATION_LINEAR) { + if (mCalibration.haveToolAreaLinearScale) { + mLocked.toolAreaLinearScale = mCalibration.toolAreaLinearScale; + } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) { + mLocked.toolAreaLinearScale = float(min(width, height)) + / mRawAxes.toolMajor.maxValue; + } + + if (mCalibration.haveToolAreaLinearBias) { + mLocked.toolAreaLinearBias = mCalibration.toolAreaLinearBias; + } + } + + mLocked.orientedRanges.haveToolArea = true; + mLocked.orientedRanges.toolMajor.min = 0; + mLocked.orientedRanges.toolMajor.max = diagonalSize; + mLocked.orientedRanges.toolMajor.flat = 0; + mLocked.orientedRanges.toolMajor.fuzz = 0; + mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor; + } + + // Pressure factors. + if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) { + RawAbsoluteAxisInfo rawPressureAxis; + switch (mCalibration.pressureSource) { + case Calibration::PRESSURE_SOURCE_PRESSURE: + rawPressureAxis = mRawAxes.pressure; + break; + case Calibration::PRESSURE_SOURCE_TOUCH: + rawPressureAxis = mRawAxes.touchMajor; + break; + default: + rawPressureAxis.clear(); + } + + mLocked.pressureScale = 0; + if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL + || mCalibration.pressureCalibration + == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) { + if (mCalibration.havePressureScale) { + mLocked.pressureScale = mCalibration.pressureScale; + } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) { + mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue; + } + } + + mLocked.orientedRanges.havePressure = true; + mLocked.orientedRanges.pressure.min = 0; + mLocked.orientedRanges.pressure.max = 1.0; + mLocked.orientedRanges.pressure.flat = 0; + mLocked.orientedRanges.pressure.fuzz = 0; + } + + // Size factors. + if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) { + mLocked.sizeScale = 0; + if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) { + if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) { + mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue; + } + } - InputDeviceInfo::MotionRange area; - area.min = 0.0f; - area.max = diagonal; - area.flat = 0.0f; - area.fuzz = diagonalFuzz; + mLocked.orientedRanges.haveSize = true; + mLocked.orientedRanges.size.min = 0; + mLocked.orientedRanges.size.max = 1.0; + mLocked.orientedRanges.size.flat = 0; + mLocked.orientedRanges.size.fuzz = 0; + } - mLocked.orientedRanges.touchMajor = area; - mLocked.orientedRanges.touchMinor = area; + // Orientation + if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) { + mLocked.orientationScale = 0; + if (mCalibration.orientationCalibration + == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) { + if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) { + mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue; + } + } - mLocked.orientedRanges.toolMajor = area; - mLocked.orientedRanges.toolMinor = area; + mLocked.orientedRanges.orientation.min = - M_PI_2; + mLocked.orientedRanges.orientation.max = M_PI_2; + mLocked.orientedRanges.orientation.flat = 0; + mLocked.orientedRanges.orientation.fuzz = 0; + } } if (orientationChanged || sizeChanged) { @@ -1322,10 +1504,10 @@ bool TouchInputMapper::configureSurfaceLocked() { } void TouchInputMapper::configureVirtualKeysLocked() { - assert(mAxes.x.valid && mAxes.y.valid); + assert(mRawAxes.x.valid && mRawAxes.y.valid); // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock. - Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions; + Vector<VirtualKeyDefinition> virtualKeyDefinitions; getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions); mLocked.virtualKeys.clear(); @@ -1336,13 +1518,13 @@ void TouchInputMapper::configureVirtualKeysLocked() { mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size()); - int32_t touchScreenLeft = mAxes.x.minValue; - int32_t touchScreenTop = mAxes.y.minValue; - int32_t touchScreenWidth = mAxes.x.getRange(); - int32_t touchScreenHeight = mAxes.y.getRange(); + int32_t touchScreenLeft = mRawAxes.x.minValue; + int32_t touchScreenTop = mRawAxes.y.minValue; + int32_t touchScreenWidth = mRawAxes.x.getRange(); + int32_t touchScreenHeight = mRawAxes.y.getRange(); for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) { - const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition = + const VirtualKeyDefinition& virtualKeyDefinition = virtualKeyDefinitions[i]; mLocked.virtualKeys.add(); @@ -1353,7 +1535,8 @@ void TouchInputMapper::configureVirtualKeysLocked() { uint32_t flags; if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode, & keyCode, & flags)) { - LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode); + LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring", + virtualKey.scanCode); mLocked.virtualKeys.pop(); // drop the key continue; } @@ -1374,12 +1557,316 @@ void TouchInputMapper::configureVirtualKeysLocked() { virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop; - LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d", + LOGI(INDENT "VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d", virtualKey.scanCode, virtualKey.keyCode, virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom); } } +void TouchInputMapper::parseCalibration() { + const InputDeviceCalibration& in = getDevice()->getCalibration(); + Calibration& out = mCalibration; + + // Touch Area + out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_DEFAULT; + String8 touchAreaCalibrationString; + if (in.tryGetProperty(String8("touch.touchArea.calibration"), touchAreaCalibrationString)) { + if (touchAreaCalibrationString == "none") { + out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE; + } else if (touchAreaCalibrationString == "geometric") { + out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC; + } else if (touchAreaCalibrationString == "pressure") { + out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE; + } else if (touchAreaCalibrationString != "default") { + LOGW("Invalid value for touch.touchArea.calibration: '%s'", + touchAreaCalibrationString.string()); + } + } + + // Tool Area + out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_DEFAULT; + String8 toolAreaCalibrationString; + if (in.tryGetProperty(String8("tool.toolArea.calibration"), toolAreaCalibrationString)) { + if (toolAreaCalibrationString == "none") { + out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE; + } else if (toolAreaCalibrationString == "geometric") { + out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC; + } else if (toolAreaCalibrationString == "linear") { + out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR; + } else if (toolAreaCalibrationString != "default") { + LOGW("Invalid value for tool.toolArea.calibration: '%s'", + toolAreaCalibrationString.string()); + } + } + + out.haveToolAreaLinearScale = in.tryGetProperty(String8("touch.toolArea.linearScale"), + out.toolAreaLinearScale); + out.haveToolAreaLinearBias = in.tryGetProperty(String8("touch.toolArea.linearBias"), + out.toolAreaLinearBias); + out.haveToolAreaIsSummed = in.tryGetProperty(String8("touch.toolArea.isSummed"), + out.toolAreaIsSummed); + + // Pressure + out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT; + String8 pressureCalibrationString; + if (in.tryGetProperty(String8("tool.pressure.calibration"), pressureCalibrationString)) { + if (pressureCalibrationString == "none") { + out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE; + } else if (pressureCalibrationString == "physical") { + out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL; + } else if (pressureCalibrationString == "amplitude") { + out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE; + } else if (pressureCalibrationString != "default") { + LOGW("Invalid value for tool.pressure.calibration: '%s'", + pressureCalibrationString.string()); + } + } + + out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT; + String8 pressureSourceString; + if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) { + if (pressureSourceString == "pressure") { + out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE; + } else if (pressureSourceString == "touch") { + out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH; + } else if (pressureSourceString != "default") { + LOGW("Invalid value for touch.pressure.source: '%s'", + pressureSourceString.string()); + } + } + + out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"), + out.pressureScale); + + // Size + out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT; + String8 sizeCalibrationString; + if (in.tryGetProperty(String8("tool.size.calibration"), sizeCalibrationString)) { + if (sizeCalibrationString == "none") { + out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE; + } else if (sizeCalibrationString == "normalized") { + out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED; + } else if (sizeCalibrationString != "default") { + LOGW("Invalid value for tool.size.calibration: '%s'", + sizeCalibrationString.string()); + } + } + + // Orientation + out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT; + String8 orientationCalibrationString; + if (in.tryGetProperty(String8("tool.orientation.calibration"), orientationCalibrationString)) { + if (orientationCalibrationString == "none") { + out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE; + } else if (orientationCalibrationString == "interpolated") { + out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED; + } else if (orientationCalibrationString != "default") { + LOGW("Invalid value for tool.orientation.calibration: '%s'", + orientationCalibrationString.string()); + } + } +} + +void TouchInputMapper::resolveCalibration() { + // Pressure + switch (mCalibration.pressureSource) { + case Calibration::PRESSURE_SOURCE_DEFAULT: + if (mRawAxes.pressure.valid) { + mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE; + } else if (mRawAxes.touchMajor.valid) { + mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH; + } + break; + + case Calibration::PRESSURE_SOURCE_PRESSURE: + if (! mRawAxes.pressure.valid) { + LOGW("Calibration property touch.pressure.source is 'pressure' but " + "the pressure axis is not available."); + } + break; + + case Calibration::PRESSURE_SOURCE_TOUCH: + if (! mRawAxes.touchMajor.valid) { + LOGW("Calibration property touch.pressure.source is 'touch' but " + "the touchMajor axis is not available."); + } + break; + + default: + break; + } + + switch (mCalibration.pressureCalibration) { + case Calibration::PRESSURE_CALIBRATION_DEFAULT: + if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) { + mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE; + } else { + mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE; + } + break; + + default: + break; + } + + // Tool Area + switch (mCalibration.toolAreaCalibration) { + case Calibration::TOOL_AREA_CALIBRATION_DEFAULT: + if (mRawAxes.toolMajor.valid) { + mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR; + } else { + mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE; + } + break; + + default: + break; + } + + // Touch Area + switch (mCalibration.touchAreaCalibration) { + case Calibration::TOUCH_AREA_CALIBRATION_DEFAULT: + if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE + && mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) { + mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE; + } else { + mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE; + } + break; + + default: + break; + } + + // Size + switch (mCalibration.sizeCalibration) { + case Calibration::SIZE_CALIBRATION_DEFAULT: + if (mRawAxes.toolMajor.valid) { + mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED; + } else { + mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE; + } + break; + + default: + break; + } + + // Orientation + switch (mCalibration.orientationCalibration) { + case Calibration::ORIENTATION_CALIBRATION_DEFAULT: + if (mRawAxes.orientation.valid) { + mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED; + } else { + mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE; + } + break; + + default: + break; + } +} + +void TouchInputMapper::logCalibration() { + // Touch Area + switch (mCalibration.touchAreaCalibration) { + case Calibration::TOUCH_AREA_CALIBRATION_NONE: + LOGI(INDENT " touch.touchArea.calibration: none"); + break; + case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC: + LOGI(INDENT " touch.touchArea.calibration: geometric"); + break; + case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE: + LOGI(INDENT " touch.touchArea.calibration: pressure"); + break; + default: + assert(false); + } + + // Tool Area + switch (mCalibration.toolAreaCalibration) { + case Calibration::TOOL_AREA_CALIBRATION_NONE: + LOGI(INDENT " touch.toolArea.calibration: none"); + break; + case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC: + LOGI(INDENT " touch.toolArea.calibration: geometric"); + break; + case Calibration::TOOL_AREA_CALIBRATION_LINEAR: + LOGI(INDENT " touch.toolArea.calibration: linear"); + break; + default: + assert(false); + } + + if (mCalibration.haveToolAreaLinearScale) { + LOGI(INDENT " touch.toolArea.linearScale: %f", mCalibration.toolAreaLinearScale); + } + + if (mCalibration.haveToolAreaLinearBias) { + LOGI(INDENT " touch.toolArea.linearBias: %f", mCalibration.toolAreaLinearBias); + } + + if (mCalibration.haveToolAreaIsSummed) { + LOGI(INDENT " touch.toolArea.isSummed: %d", mCalibration.toolAreaIsSummed); + } + + // Pressure + switch (mCalibration.pressureCalibration) { + case Calibration::PRESSURE_CALIBRATION_NONE: + LOGI(INDENT " touch.pressure.calibration: none"); + break; + case Calibration::PRESSURE_CALIBRATION_PHYSICAL: + LOGI(INDENT " touch.pressure.calibration: physical"); + break; + case Calibration::PRESSURE_CALIBRATION_AMPLITUDE: + LOGI(INDENT " touch.pressure.calibration: amplitude"); + break; + default: + assert(false); + } + + switch (mCalibration.pressureSource) { + case Calibration::PRESSURE_SOURCE_PRESSURE: + LOGI(INDENT " touch.pressure.source: pressure"); + break; + case Calibration::PRESSURE_SOURCE_TOUCH: + LOGI(INDENT " touch.pressure.source: touch"); + break; + case Calibration::PRESSURE_SOURCE_DEFAULT: + break; + default: + assert(false); + } + + if (mCalibration.havePressureScale) { + LOGI(INDENT " touch.pressure.scale: %f", mCalibration.pressureScale); + } + + // Size + switch (mCalibration.sizeCalibration) { + case Calibration::SIZE_CALIBRATION_NONE: + LOGI(INDENT " touch.size.calibration: none"); + break; + case Calibration::SIZE_CALIBRATION_NORMALIZED: + LOGI(INDENT " touch.size.calibration: normalized"); + break; + default: + assert(false); + } + + // Orientation + switch (mCalibration.orientationCalibration) { + case Calibration::ORIENTATION_CALIBRATION_NONE: + LOGI(INDENT " touch.orientation.calibration: none"); + break; + case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED: + LOGI(INDENT " touch.orientation.calibration: interpolated"); + break; + default: + assert(false); + } +} + void TouchInputMapper::reset() { // Synthesize touch up event if touch is currently down. // This will also take care of finishing virtual key processing if needed. @@ -1584,13 +2071,14 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { // The dispatcher takes care of batching moves so we don't have to deal with that here. int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE; dispatchTouch(when, policyFlags, & mCurrentTouch, - currentIdBits, -1, motionEventAction); + currentIdBits, -1, currentPointerCount, motionEventAction); } else { // There may be pointers going up and pointers going down at the same time when pointer // ids are reported by the device driver. BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value); BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value); BitSet32 activeIdBits(lastIdBits.value); + uint32_t pointerCount = lastPointerCount; while (! upIdBits.isEmpty()) { uint32_t upId = upIdBits.firstMarkedBit(); @@ -1606,7 +2094,8 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { } dispatchTouch(when, policyFlags, & mLastTouch, - oldActiveIdBits, upId, motionEventAction); + oldActiveIdBits, upId, pointerCount, motionEventAction); + pointerCount -= 1; } while (! downIdBits.isEmpty()) { @@ -1623,16 +2112,16 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN; } + pointerCount += 1; dispatchTouch(when, policyFlags, & mCurrentTouch, - activeIdBits, downId, motionEventAction); + activeIdBits, downId, pointerCount, motionEventAction); } } } void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, - TouchData* touch, BitSet32 idBits, uint32_t changedId, + TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount, int32_t motionEventAction) { - uint32_t pointerCount = 0; int32_t pointerIds[MAX_POINTERS]; PointerCoords pointerCoords[MAX_POINTERS]; int32_t motionEventEdgeFlags = 0; @@ -1643,36 +2132,130 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, // Walk through the the active pointers and map touch screen coordinates (TouchData) into // display coordinates (PointerCoords) and adjust for display orientation. - while (! idBits.isEmpty()) { + for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) { uint32_t id = idBits.firstMarkedBit(); idBits.clearBit(id); - uint32_t index = touch->idToIndex[id]; - - float x = float(touch->pointers[index].x - mLocked.xOrigin) * mLocked.xScale; - float y = float(touch->pointers[index].y - mLocked.yOrigin) * mLocked.yScale; - float pressure = float(touch->pointers[index].pressure - mLocked.pressureOrigin) - * mLocked.pressureScale; - float size = float(touch->pointers[index].size - mLocked.sizeOrigin) - * mLocked.sizeScale; - - float orientation = float(touch->pointers[index].orientation) - * mLocked.orientationScale; - - float touchMajor, touchMinor, toolMajor, toolMinor; - if (abs(orientation) <= M_PI_4) { - // Nominally vertical orientation: scale major axis by Y, and scale minor axis by X. - touchMajor = float(touch->pointers[index].touchMajor) * mLocked.yScale; - touchMinor = float(touch->pointers[index].touchMinor) * mLocked.xScale; - toolMajor = float(touch->pointers[index].toolMajor) * mLocked.yScale; - toolMinor = float(touch->pointers[index].toolMinor) * mLocked.xScale; - } else { - // Nominally horizontal orientation: scale major axis by X, and scale minor axis by Y. - touchMajor = float(touch->pointers[index].touchMajor) * mLocked.xScale; - touchMinor = float(touch->pointers[index].touchMinor) * mLocked.yScale; - toolMajor = float(touch->pointers[index].toolMajor) * mLocked.xScale; - toolMinor = float(touch->pointers[index].toolMinor) * mLocked.yScale; + uint32_t inIndex = touch->idToIndex[id]; + + const PointerData& in = touch->pointers[inIndex]; + + // X and Y + float x = float(in.x - mLocked.xOrigin) * mLocked.xScale; + float y = float(in.y - mLocked.yOrigin) * mLocked.yScale; + + // ToolMajor and ToolMinor + float toolMajor, toolMinor; + switch (mCalibration.toolAreaCalibration) { + case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC: + toolMajor = in.toolMajor * mLocked.geometricScale; + if (mRawAxes.toolMinor.valid) { + toolMinor = in.toolMinor * mLocked.geometricScale; + } else { + toolMinor = toolMajor; + } + break; + case Calibration::TOOL_AREA_CALIBRATION_LINEAR: + toolMajor = in.toolMajor != 0 + ? in.toolMajor * mLocked.toolAreaLinearScale + mLocked.toolAreaLinearBias + : 0; + if (mRawAxes.toolMinor.valid) { + toolMinor = in.toolMinor != 0 + ? in.toolMinor * mLocked.toolAreaLinearScale + + mLocked.toolAreaLinearBias + : 0; + } else { + toolMinor = toolMajor; + } + break; + default: + toolMajor = 0; + toolMinor = 0; + break; + } + + if (mCalibration.haveToolAreaIsSummed && mCalibration.toolAreaIsSummed) { + toolMajor /= pointerCount; + toolMinor /= pointerCount; + } + + // Pressure + float rawPressure; + switch (mCalibration.pressureSource) { + case Calibration::PRESSURE_SOURCE_PRESSURE: + rawPressure = in.pressure; + break; + case Calibration::PRESSURE_SOURCE_TOUCH: + rawPressure = in.touchMajor; + break; + default: + rawPressure = 0; + } + + float pressure; + switch (mCalibration.pressureCalibration) { + case Calibration::PRESSURE_CALIBRATION_PHYSICAL: + case Calibration::PRESSURE_CALIBRATION_AMPLITUDE: + pressure = rawPressure * mLocked.pressureScale; + break; + default: + pressure = 1; + break; + } + + // TouchMajor and TouchMinor + float touchMajor, touchMinor; + switch (mCalibration.touchAreaCalibration) { + case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC: + touchMajor = in.touchMajor * mLocked.geometricScale; + if (mRawAxes.touchMinor.valid) { + touchMinor = in.touchMinor * mLocked.geometricScale; + } else { + touchMinor = touchMajor; + } + break; + case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE: + touchMajor = toolMajor * pressure; + touchMinor = toolMinor * pressure; + break; + default: + touchMajor = 0; + touchMinor = 0; + break; + } + + if (touchMajor > toolMajor) { + touchMajor = toolMajor; + } + if (touchMinor > toolMinor) { + touchMinor = toolMinor; + } + + // Size + float size; + switch (mCalibration.sizeCalibration) { + case Calibration::SIZE_CALIBRATION_NORMALIZED: { + float rawSize = mRawAxes.toolMinor.valid + ? avg(in.toolMajor, in.toolMinor) + : in.toolMajor; + size = rawSize * mLocked.sizeScale; + break; + } + default: + size = 0; + break; } + // Orientation + float orientation; + switch (mCalibration.orientationCalibration) { + case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED: + orientation = in.orientation * mLocked.orientationScale; + break; + default: + orientation = 0; + } + + // Adjust coords for orientation. switch (mLocked.surfaceOrientation) { case InputReaderPolicyInterface::ROTATION_90: { float xTemp = x; @@ -1702,23 +2285,23 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, } } - pointerIds[pointerCount] = int32_t(id); + // Write output coords. + PointerCoords& out = pointerCoords[outIndex]; + out.x = x; + out.y = y; + out.pressure = pressure; + out.size = size; + out.touchMajor = touchMajor; + out.touchMinor = touchMinor; + out.toolMajor = toolMajor; + out.toolMinor = toolMinor; + out.orientation = orientation; - pointerCoords[pointerCount].x = x; - pointerCoords[pointerCount].y = y; - pointerCoords[pointerCount].pressure = pressure; - pointerCoords[pointerCount].size = size; - pointerCoords[pointerCount].touchMajor = touchMajor; - pointerCoords[pointerCount].touchMinor = touchMinor; - pointerCoords[pointerCount].toolMajor = toolMajor; - pointerCoords[pointerCount].toolMinor = toolMinor; - pointerCoords[pointerCount].orientation = orientation; + pointerIds[outIndex] = int32_t(id); if (id == changedId) { - motionEventAction |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; } - - pointerCount += 1; } // Check edge flags by looking only at the first pointer since the flags are @@ -1747,9 +2330,9 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, } bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) { - if (mAxes.x.valid && mAxes.y.valid) { - return x >= mAxes.x.minValue && x <= mAxes.x.maxValue - && y >= mAxes.y.minValue && y <= mAxes.y.maxValue; + if (mRawAxes.x.valid && mRawAxes.y.valid) { + return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue + && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue; } return true; } @@ -1960,7 +2543,7 @@ void TouchInputMapper::calculatePointerIds() { * then drop it. */ bool TouchInputMapper::applyBadTouchFilter() { // This hack requires valid axis parameters. - if (! mAxes.y.valid) { + if (! mRawAxes.y.valid) { return false; } @@ -1982,7 +2565,7 @@ bool TouchInputMapper::applyBadTouchFilter() { // the long size of the screen to be bad. This was a magic value // determined by looking at the maximum distance it is feasible // to actually move in one sample. - int32_t maxDeltaY = mAxes.y.getRange() * 7 / 16; + int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16; // XXX The original code in InputDevice.java included commented out // code for testing the X axis. Note that when we drop a point @@ -2044,7 +2627,7 @@ bool TouchInputMapper::applyBadTouchFilter() { */ bool TouchInputMapper::applyJumpyTouchFilter() { // This hack requires valid axis parameters. - if (! mAxes.y.valid) { + if (! mRawAxes.y.valid) { return false; } @@ -2104,7 +2687,7 @@ bool TouchInputMapper::applyJumpyTouchFilter() { } if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) { - int jumpyEpsilon = mAxes.y.getRange() / JUMPY_EPSILON_DIVISOR; + int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR; // We only replace the single worst jumpy point as characterized by pointer distance // in a single axis. @@ -2209,7 +2792,18 @@ void TouchInputMapper::applyAveragingTouchFilter() { uint32_t id = mCurrentTouch.pointers[currentIndex].id; int32_t x = mCurrentTouch.pointers[currentIndex].x; int32_t y = mCurrentTouch.pointers[currentIndex].y; - int32_t pressure = mCurrentTouch.pointers[currentIndex].pressure; + int32_t pressure; + switch (mCalibration.pressureSource) { + case Calibration::PRESSURE_SOURCE_PRESSURE: + pressure = mCurrentTouch.pointers[currentIndex].pressure; + break; + case Calibration::PRESSURE_SOURCE_TOUCH: + pressure = mCurrentTouch.pointers[currentIndex].touchMajor; + break; + default: + pressure = 1; + break; + } if (mLastTouch.idBits.hasBit(id)) { // Pointer was down before and is still down now. @@ -2274,17 +2868,19 @@ void TouchInputMapper::applyAveragingTouchFilter() { } } - averagedX /= totalPressure; - averagedY /= totalPressure; + if (totalPressure != 0) { + averagedX /= totalPressure; + averagedY /= totalPressure; #if DEBUG_HACKS - LOGD("AveragingTouchFilter: Pointer id %d - " - "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure, - averagedX, averagedY); + LOGD("AveragingTouchFilter: Pointer id %d - " + "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure, + averagedX, averagedY); #endif - mCurrentTouch.pointers[currentIndex].x = averagedX; - mCurrentTouch.pointers[currentIndex].y = averagedY; + mCurrentTouch.pointers[currentIndex].x = averagedX; + mCurrentTouch.pointers[currentIndex].y = averagedY; + } } else { #if DEBUG_HACKS LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id); @@ -2382,8 +2978,8 @@ void SingleTouchInputMapper::initialize() { mDown = false; mX = 0; mY = 0; - mPressure = 1; // default to 1 for devices that don't report pressure - mSize = 0; // default to 0 for devices that don't report size + mPressure = 0; // default to 0 for devices that don't report pressure + mToolWidth = 0; // default to 0 for devices that don't report tool width } void SingleTouchInputMapper::reset() { @@ -2460,7 +3056,7 @@ void SingleTouchInputMapper::sync(nsecs_t when) { } if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) { - mSize = mAccumulator.absToolWidth; + mToolWidth = mAccumulator.absToolWidth; } mCurrentTouch.clear(); @@ -2471,11 +3067,10 @@ void SingleTouchInputMapper::sync(nsecs_t when) { mCurrentTouch.pointers[0].x = mX; mCurrentTouch.pointers[0].y = mY; mCurrentTouch.pointers[0].pressure = mPressure; - mCurrentTouch.pointers[0].size = mSize; - mCurrentTouch.pointers[0].touchMajor = mSize; - mCurrentTouch.pointers[0].touchMinor = mSize; - mCurrentTouch.pointers[0].toolMajor = mSize; - mCurrentTouch.pointers[0].toolMinor = mSize; + mCurrentTouch.pointers[0].touchMajor = 0; + mCurrentTouch.pointers[0].touchMinor = 0; + mCurrentTouch.pointers[0].toolMajor = mToolWidth; + mCurrentTouch.pointers[0].toolMinor = mToolWidth; mCurrentTouch.pointers[0].orientation = 0; mCurrentTouch.idToIndex[0] = 0; mCurrentTouch.idBits.markBit(0); @@ -2486,20 +3081,13 @@ void SingleTouchInputMapper::sync(nsecs_t when) { mAccumulator.clear(); } -void SingleTouchInputMapper::configureAxes() { - TouchInputMapper::configureAxes(); - - // The axes are aliased to take into account the manner in which they are presented - // as part of the TouchData during the sync. - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mAxes.x); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mAxes.y); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mAxes.pressure); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mAxes.size); +void SingleTouchInputMapper::configureRawAxes() { + TouchInputMapper::configureRawAxes(); - mAxes.touchMajor = mAxes.size; - mAxes.touchMinor = mAxes.size; - mAxes.toolMajor = mAxes.size; - mAxes.toolMinor = mAxes.size; + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor); } @@ -2562,6 +3150,10 @@ void MultiTouchInputMapper::process(const RawEvent* rawEvent) { pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID; pointer->absMTTrackingId = rawEvent->value; break; + case ABS_MT_PRESSURE: + pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE; + pointer->absMTPressure = rawEvent->value; + break; } break; } @@ -2596,8 +3188,7 @@ void MultiTouchInputMapper::process(const RawEvent* rawEvent) { void MultiTouchInputMapper::sync(nsecs_t when) { static const uint32_t REQUIRED_FIELDS = - Accumulator::FIELD_ABS_MT_POSITION_X - | Accumulator::FIELD_ABS_MT_POSITION_Y; + Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y; uint32_t inCount = mAccumulator.pointerCount; uint32_t outCount = 0; @@ -2619,60 +3210,59 @@ void MultiTouchInputMapper::sync(nsecs_t when) { outPointer.x = inPointer.absMTPositionX; outPointer.y = inPointer.absMTPositionY; + if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) { + if (inPointer.absMTPressure <= 0) { + // Some devices send sync packets with X / Y but with a 0 presure to indicate + // a pointer up. Drop this finger. + continue; + } + outPointer.pressure = inPointer.absMTPressure; + } else { + // Default pressure to 0 if absent. + outPointer.pressure = 0; + } + if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) { - int32_t value = inPointer.absMTTouchMajor; - if (value <= 0) { + if (inPointer.absMTTouchMajor <= 0) { // Some devices send sync packets with X / Y but with a 0 touch major to indicate - // a pointer up. Drop this finger. + // a pointer going up. Drop this finger. continue; } outPointer.touchMajor = inPointer.absMTTouchMajor; } else { + // Default touch area to 0 if absent. outPointer.touchMajor = 0; } if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) { outPointer.touchMinor = inPointer.absMTTouchMinor; } else { + // Assume touch area is circular. outPointer.touchMinor = outPointer.touchMajor; } if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) { outPointer.toolMajor = inPointer.absMTWidthMajor; } else { - outPointer.toolMajor = outPointer.touchMajor; + // Default tool area to 0 if absent. + outPointer.toolMajor = 0; } if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) { outPointer.toolMinor = inPointer.absMTWidthMinor; } else { + // Assume tool area is circular. outPointer.toolMinor = outPointer.toolMajor; } if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) { outPointer.orientation = inPointer.absMTOrientation; } else { + // Default orientation to vertical if absent. 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; - + // Assign pointer id using tracking id if available. if (havePointerIds) { if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) { uint32_t id = uint32_t(inPointer.absMTTrackingId); @@ -2705,33 +3295,17 @@ void MultiTouchInputMapper::sync(nsecs_t when) { mAccumulator.clear(); } -void MultiTouchInputMapper::configureAxes() { - TouchInputMapper::configureAxes(); - - // The axes are aliased to take into account the manner in which they are presented - // as part of the TouchData during the sync. - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mAxes.x); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mAxes.y); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mAxes.touchMajor); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mAxes.touchMinor); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mAxes.toolMajor); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mAxes.toolMinor); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mAxes.orientation); - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mAxes.pressure); - - if (! mAxes.touchMinor.valid) { - mAxes.touchMinor = mAxes.touchMajor; - } - - if (! mAxes.toolMinor.valid) { - mAxes.toolMinor = mAxes.toolMajor; - } - - if (! mAxes.pressure.valid) { - mAxes.pressure = mAxes.touchMajor; - } +void MultiTouchInputMapper::configureRawAxes() { + TouchInputMapper::configureRawAxes(); - mAxes.size = mAxes.toolMajor; + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation); + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure); } |