Skip to content

Commit 6d2e24f

Browse files
author
Michael Checo
committed
Add support to disable mouse acceleration
Bug: 382276176 Test: atest CursorInputMapperUnitTest Flag: com.android.hardware.input.pointer_acceleration Change-Id: I431ac6fa3b918b1d292528f614e06532837c4a82
1 parent e7f052d commit 6d2e24f

6 files changed

Lines changed: 100 additions & 11 deletions

File tree

include/input/AccelerationCurve.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,15 @@ struct AccelerationCurveSegment {
4646
std::vector<AccelerationCurveSegment> createAccelerationCurveForPointerSensitivity(
4747
int32_t sensitivity);
4848

49+
/*
50+
* Creates a flat acceleration curve for disabling pointer acceleration.
51+
*
52+
* This method generates a single AccelerationCurveSegment with specific values
53+
* to effectively disable acceleration for both mice and touchpads.
54+
* A flat acceleration curve ensures a constant gain, meaning that the output
55+
* velocity is directly proportional to the input velocity, resulting in
56+
* a 1:1 movement ratio between the input device and the on-screen pointer.
57+
*/
58+
std::vector<AccelerationCurveSegment> createFlatAccelerationCurve(int32_t sensitivity);
59+
4960
} // namespace android

libs/input/AccelerationCurve.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@ static_assert(kSegments.back().maxPointerSpeedMmPerS == std::numeric_limits<doub
4040
constexpr std::array<double, 15> kSensitivityFactors = {1, 2, 4, 6, 7, 8, 9, 10,
4141
11, 12, 13, 14, 16, 18, 20};
4242

43+
// Calculates the base gain for a given pointer sensitivity value.
44+
//
45+
// The base gain is a scaling factor that is applied to the pointer movement.
46+
// Higher sensitivity values result in larger base gains, which in turn result
47+
// in faster pointer movements.
48+
//
49+
// The base gain is calculated using a linear mapping function that maps the
50+
// sensitivity range [-7, 7] to a base gain range [0.5, 2.0].
51+
double calculateBaseGain(int32_t sensitivity) {
52+
return 0.5 + (sensitivity + 7) * (2.0 - 0.5) / (7 + 7);
53+
}
54+
4355
} // namespace
4456

4557
std::vector<AccelerationCurveSegment> createAccelerationCurveForPointerSensitivity(
@@ -60,4 +72,13 @@ std::vector<AccelerationCurveSegment> createAccelerationCurveForPointerSensitivi
6072
return output;
6173
}
6274

75+
std::vector<AccelerationCurveSegment> createFlatAccelerationCurve(int32_t sensitivity) {
76+
LOG_ALWAYS_FATAL_IF(sensitivity < -7 || sensitivity > 7, "Invalid pointer sensitivity value");
77+
std::vector<AccelerationCurveSegment> output = {
78+
AccelerationCurveSegment{std::numeric_limits<double>::infinity(),
79+
calculateBaseGain(sensitivity),
80+
/* reciprocal = */ 0}};
81+
return output;
82+
}
83+
6384
} // namespace android

services/inputflinger/include/InputReaderBase.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,17 @@ struct InputReaderConfiguration {
139139
// The mouse pointer speed, as a number from -7 (slowest) to 7 (fastest).
140140
int32_t mousePointerSpeed;
141141

142-
// Displays on which an acceleration curve shouldn't be applied for pointer movements from mice.
142+
// Displays on which all pointer scaling, including linear scaling based on the
143+
// user's pointer speed setting, should be disabled for mice. This differs from
144+
// disabling acceleration via the 'mousePointerAccelerationEnabled' setting, where
145+
// the pointer speed setting still influences the scaling factor.
143146
std::set<ui::LogicalDisplayId> displaysWithMousePointerAccelerationDisabled;
144147

148+
// True if the connected mouse should exhibit pointer acceleration. If false,
149+
// a flat acceleration curve (linear scaling) is used, but the user's pointer
150+
// speed setting still affects the scaling factor.
151+
bool mousePointerAccelerationEnabled;
152+
145153
// Velocity control parameters for touchpad pointer movements on the old touchpad stack (based
146154
// on TouchInputMapper).
147155
//
@@ -275,6 +283,7 @@ struct InputReaderConfiguration {
275283
defaultPointerDisplayId(ui::LogicalDisplayId::DEFAULT),
276284
mousePointerSpeed(0),
277285
displaysWithMousePointerAccelerationDisabled(),
286+
mousePointerAccelerationEnabled(true),
278287
pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f,
279288
static_cast<float>(
280289
android::os::IInputConstants::

services/inputflinger/reader/mapper/CursorInputMapper.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -481,15 +481,21 @@ void CursorInputMapper::configureOnChangePointerSpeed(const InputReaderConfigura
481481
mPointerVelocityControl.setAccelerationEnabled(false);
482482
mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
483483
mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
484-
} else {
485-
mPointerVelocityControl.setAccelerationEnabled(
486-
config.displaysWithMousePointerAccelerationDisabled.count(
487-
mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0);
488-
mPointerVelocityControl.setCurve(
489-
createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed));
490-
mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters);
491-
mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters);
484+
return;
492485
}
486+
487+
bool disableAllScaling = config.displaysWithMousePointerAccelerationDisabled.count(
488+
mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) != 0;
489+
490+
mPointerVelocityControl.setAccelerationEnabled(!disableAllScaling);
491+
492+
mPointerVelocityControl.setCurve(
493+
config.mousePointerAccelerationEnabled
494+
? createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed)
495+
: createFlatAccelerationCurve(config.mousePointerSpeed));
496+
497+
mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters);
498+
mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters);
493499
}
494500

495501
void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfiguration& config) {

services/inputflinger/tests/CursorInputMapper_test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <com_android_input_flags.h>
2828
#include <gmock/gmock.h>
2929
#include <gtest/gtest.h>
30+
#include <input/AccelerationCurve.h>
3031
#include <input/DisplayViewport.h>
3132
#include <input/InputEventLabels.h>
3233
#include <linux/input-event-codes.h>
@@ -1028,6 +1029,34 @@ TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdNoAssociatedViewport) {
10281029
WithCoords(0.0f, 0.0f)))));
10291030
}
10301031

1032+
TEST_F(CursorInputMapperUnitTest, PointerAccelerationDisabled) {
1033+
mReaderConfiguration.mousePointerAccelerationEnabled = false;
1034+
mReaderConfiguration.mousePointerSpeed = 3;
1035+
mPropertyMap.addProperty("cursor.mode", "pointer");
1036+
createMapper();
1037+
1038+
std::list<NotifyArgs> reconfigureArgs;
1039+
1040+
reconfigureArgs += mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
1041+
InputReaderConfiguration::Change::POINTER_SPEED);
1042+
1043+
std::vector<AccelerationCurveSegment> curve =
1044+
createFlatAccelerationCurve(mReaderConfiguration.mousePointerSpeed);
1045+
double baseGain = curve[0].baseGain;
1046+
1047+
std::list<NotifyArgs> motionArgs;
1048+
motionArgs += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
1049+
motionArgs += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
1050+
motionArgs += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
1051+
1052+
const float expectedRelX = 10 * baseGain;
1053+
const float expectedRelY = 20 * baseGain;
1054+
ASSERT_THAT(motionArgs,
1055+
ElementsAre(VariantWith<NotifyMotionArgs>(
1056+
AllOf(WithMotionAction(HOVER_MOVE),
1057+
WithRelativeMotion(expectedRelX, expectedRelY)))));
1058+
}
1059+
10311060
TEST_F(CursorInputMapperUnitTest, ConfigureAccelerationWithAssociatedViewport) {
10321061
mPropertyMap.addProperty("cursor.mode", "pointer");
10331062
DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation0);

services/inputflinger/tests/TestEventMatchers.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@
3232

3333
namespace android {
3434

35+
namespace {
36+
37+
template <typename T>
38+
static bool valuesMatch(T value1, T value2) {
39+
if constexpr (std::is_floating_point_v<T>) {
40+
return std::abs(value1 - value2) < EPSILON;
41+
} else {
42+
return value1 == value2;
43+
}
44+
}
45+
3546
struct PointF {
3647
float x;
3748
float y;
@@ -42,6 +53,8 @@ inline std::string pointFToString(const PointF& p) {
4253
return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
4354
}
4455

56+
} // namespace
57+
4558
/// Source
4659
class WithSourceMatcher {
4760
public:
@@ -706,8 +719,8 @@ class WithRelativeMotionMatcher {
706719
}
707720

708721
const PointerCoords& coords = event.pointerCoords[mPointerIndex];
709-
bool matches = mRelX == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) &&
710-
mRelY == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
722+
bool matches = valuesMatch(mRelX, coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X)) &&
723+
valuesMatch(mRelY, coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
711724
if (!matches) {
712725
*os << "expected relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
713726
<< mPointerIndex << ", but got ("

0 commit comments

Comments
 (0)