diff options
author | 2024-05-24 08:27:45 -0700 | |
---|---|---|
committer | 2024-05-24 08:27:45 -0700 | |
commit | 5968781840bb5bead4758c9adb1e41bbea1c24c7 (patch) | |
tree | d0c6e21063ef3a2265bd3071e363ddfe9ccf618b /libs/input/VelocityControl.cpp | |
parent | a99e1cd67b5d2237200bf23b44a03e0eb31e9326 (diff) | |
parent | 8bf4487ae52ce8d1797ea58dd0b1109255518ceb (diff) |
Merge Android 24Q2 Release (ab/11526283) to aosp-main-future
Bug: 337098550
Merged-In: I8d975b81afd2cde1d543e8bc7e730a6e42393bec
Change-Id: I714982d2b0df34afc9f9729deb2636de5d0c7b64
Diffstat (limited to 'libs/input/VelocityControl.cpp')
-rw-r--r-- | libs/input/VelocityControl.cpp | 210 |
1 files changed, 146 insertions, 64 deletions
diff --git a/libs/input/VelocityControl.cpp b/libs/input/VelocityControl.cpp index c835a081a5..edd31e91d3 100644 --- a/libs/input/VelocityControl.cpp +++ b/libs/input/VelocityControl.cpp @@ -15,7 +15,6 @@ */ #define LOG_TAG "VelocityControl" -//#define LOG_NDEBUG 0 // Log debug messages about acceleration. static constexpr bool DEBUG_ACCELERATION = false; @@ -23,6 +22,7 @@ static constexpr bool DEBUG_ACCELERATION = false; #include <math.h> #include <limits.h> +#include <android-base/logging.h> #include <input/VelocityControl.h> #include <utils/BitSet.h> #include <utils/Timers.h> @@ -37,15 +37,6 @@ VelocityControl::VelocityControl() { reset(); } -const VelocityControlParameters& VelocityControl::getParameters() const{ - return mParameters; -} - -void VelocityControl::setParameters(const VelocityControlParameters& parameters) { - mParameters = parameters; - reset(); -} - void VelocityControl::reset() { mLastMovementTime = LLONG_MIN; mRawPositionX = 0; @@ -54,65 +45,156 @@ void VelocityControl::reset() { } void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) { - if ((deltaX && *deltaX) || (deltaY && *deltaY)) { - if (eventTime >= mLastMovementTime + STOP_TIME) { - if (DEBUG_ACCELERATION && mLastMovementTime != LLONG_MIN) { - ALOGD("VelocityControl: stopped, last movement was %0.3fms ago", - (eventTime - mLastMovementTime) * 0.000001f); - } - reset(); - } + if ((deltaX == nullptr || *deltaX == 0) && (deltaY == nullptr || *deltaY == 0)) { + return; + } + if (eventTime >= mLastMovementTime + STOP_TIME) { + ALOGD_IF(DEBUG_ACCELERATION && mLastMovementTime != LLONG_MIN, + "VelocityControl: stopped, last movement was %0.3fms ago", + (eventTime - mLastMovementTime) * 0.000001f); + reset(); + } - mLastMovementTime = eventTime; - if (deltaX) { - mRawPositionX += *deltaX; - } - if (deltaY) { - mRawPositionY += *deltaY; - } - mVelocityTracker.addMovement(eventTime, /*pointerId=*/0, AMOTION_EVENT_AXIS_X, - mRawPositionX); - mVelocityTracker.addMovement(eventTime, /*pointerId=*/0, AMOTION_EVENT_AXIS_Y, - mRawPositionY); - - std::optional<float> vx = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_X, 0); - std::optional<float> vy = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_Y, 0); - float scale = mParameters.scale; - if (vx && vy) { - float speed = hypotf(*vx, *vy) * scale; - if (speed >= mParameters.highThreshold) { - // Apply full acceleration above the high speed threshold. - scale *= mParameters.acceleration; - } else if (speed > mParameters.lowThreshold) { - // Linearly interpolate the acceleration to apply between the low and high - // speed thresholds. - scale *= 1 + (speed - mParameters.lowThreshold) - / (mParameters.highThreshold - mParameters.lowThreshold) - * (mParameters.acceleration - 1); - } - - if (DEBUG_ACCELERATION) { - ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): " - "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f", - mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, - mParameters.acceleration, *vx, *vy, speed, scale / mParameters.scale); - } - - } else { - if (DEBUG_ACCELERATION) { - ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity", - mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, - mParameters.acceleration); - } - } + mLastMovementTime = eventTime; + if (deltaX) { + mRawPositionX += *deltaX; + } + if (deltaY) { + mRawPositionY += *deltaY; + } + mVelocityTracker.addMovement(eventTime, /*pointerId=*/0, AMOTION_EVENT_AXIS_X, mRawPositionX); + mVelocityTracker.addMovement(eventTime, /*pointerId=*/0, AMOTION_EVENT_AXIS_Y, mRawPositionY); + scaleDeltas(deltaX, deltaY); +} + +// --- SimpleVelocityControl --- + +const VelocityControlParameters& SimpleVelocityControl::getParameters() const { + return mParameters; +} - if (deltaX) { - *deltaX *= scale; +void SimpleVelocityControl::setParameters(const VelocityControlParameters& parameters) { + mParameters = parameters; + reset(); +} + +void SimpleVelocityControl::scaleDeltas(float* deltaX, float* deltaY) { + std::optional<float> vx = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_X, 0); + std::optional<float> vy = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_Y, 0); + float scale = mParameters.scale; + if (vx.has_value() && vy.has_value()) { + float speed = hypotf(*vx, *vy) * scale; + if (speed >= mParameters.highThreshold) { + // Apply full acceleration above the high speed threshold. + scale *= mParameters.acceleration; + } else if (speed > mParameters.lowThreshold) { + // Linearly interpolate the acceleration to apply between the low and high + // speed thresholds. + scale *= 1 + + (speed - mParameters.lowThreshold) / + (mParameters.highThreshold - mParameters.lowThreshold) * + (mParameters.acceleration - 1); } - if (deltaY) { - *deltaY *= scale; + + ALOGD_IF(DEBUG_ACCELERATION, + "SimpleVelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): " + "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f", + mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, + mParameters.acceleration, *vx, *vy, speed, scale / mParameters.scale); + + } else { + ALOGD_IF(DEBUG_ACCELERATION, + "SimpleVelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity", + mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, + mParameters.acceleration); + } + + if (deltaX != nullptr) { + *deltaX *= scale; + } + if (deltaY != nullptr) { + *deltaY *= scale; + } +} + +// --- CurvedVelocityControl --- + +namespace { + +/** + * The resolution that we assume a mouse to have, in counts per inch. + * + * Mouse resolutions vary wildly, but 800 CPI is probably the most common. There should be enough + * range in the available sensitivity settings to accommodate users of mice with other resolutions. + */ +constexpr int32_t MOUSE_CPI = 800; + +float countsToMm(float counts) { + return counts / MOUSE_CPI * 25.4; +} + +} // namespace + +CurvedVelocityControl::CurvedVelocityControl() + : mCurveSegments(createAccelerationCurveForPointerSensitivity(0)) {} + +void CurvedVelocityControl::setCurve(const std::vector<AccelerationCurveSegment>& curve) { + mCurveSegments = curve; +} + +void CurvedVelocityControl::setAccelerationEnabled(bool enabled) { + mAccelerationEnabled = enabled; +} + +void CurvedVelocityControl::scaleDeltas(float* deltaX, float* deltaY) { + if (!mAccelerationEnabled) { + ALOGD_IF(DEBUG_ACCELERATION, "CurvedVelocityControl: acceleration disabled"); + return; + } + + std::optional<float> vx = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_X, 0); + std::optional<float> vy = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_Y, 0); + + float ratio; + if (vx.has_value() && vy.has_value()) { + float vxMmPerS = countsToMm(*vx); + float vyMmPerS = countsToMm(*vy); + float speedMmPerS = sqrtf(vxMmPerS * vxMmPerS + vyMmPerS * vyMmPerS); + + const AccelerationCurveSegment& seg = segmentForSpeed(speedMmPerS); + ratio = seg.baseGain + seg.reciprocal / speedMmPerS; + ALOGD_IF(DEBUG_ACCELERATION, + "CurvedVelocityControl: velocities (%0.3f, %0.3f) → speed %0.3f → ratio %0.3f", + vxMmPerS, vyMmPerS, speedMmPerS, ratio); + } else { + // We don't have enough data to compute a velocity yet. This happens early in the movement, + // when the speed is presumably low, so use the base gain of the first segment of the curve. + // (This would behave oddly for curves with a reciprocal term on the first segment, but we + // don't have any of those, and they'd be very strange at velocities close to zero anyway.) + ratio = mCurveSegments[0].baseGain; + ALOGD_IF(DEBUG_ACCELERATION, + "CurvedVelocityControl: unknown velocity, using base gain of first segment (%.3f)", + ratio); + } + + if (deltaX != nullptr) { + *deltaX *= ratio; + } + if (deltaY != nullptr) { + *deltaY *= ratio; + } +} + +const AccelerationCurveSegment& CurvedVelocityControl::segmentForSpeed(float speedMmPerS) { + for (const AccelerationCurveSegment& seg : mCurveSegments) { + if (speedMmPerS <= seg.maxPointerSpeedMmPerS) { + return seg; } } + ALOGE("CurvedVelocityControl: No segment found for speed %.3f; last segment should always have " + "a max speed of infinity.", + speedMmPerS); + return mCurveSegments.back(); } } // namespace android |