1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // clang-format off
18 #include "../Macros.h"
19 // clang-format on
20 
21 #include "CursorInputMapper.h"
22 
23 #include <optional>
24 
25 #include <com_android_input_flags.h>
26 #include <ftl/enum.h>
27 #include <input/AccelerationCurve.h>
28 
29 #include "CursorButtonAccumulator.h"
30 #include "CursorScrollAccumulator.h"
31 #include "PointerControllerInterface.h"
32 #include "TouchCursorInputMapperCommon.h"
33 
34 #include "input/PrintTools.h"
35 
36 namespace input_flags = com::android::input::flags;
37 
38 namespace android {
39 
40 // The default velocity control parameters that has no effect.
41 static const VelocityControlParameters FLAT_VELOCITY_CONTROL_PARAMS{};
42 
43 // --- CursorMotionAccumulator ---
44 
CursorMotionAccumulator()45 CursorMotionAccumulator::CursorMotionAccumulator() {
46     clearRelativeAxes();
47 }
48 
reset(InputDeviceContext & deviceContext)49 void CursorMotionAccumulator::reset(InputDeviceContext& deviceContext) {
50     clearRelativeAxes();
51 }
52 
clearRelativeAxes()53 void CursorMotionAccumulator::clearRelativeAxes() {
54     mRelX = 0;
55     mRelY = 0;
56 }
57 
process(const RawEvent & rawEvent)58 void CursorMotionAccumulator::process(const RawEvent& rawEvent) {
59     if (rawEvent.type == EV_REL) {
60         switch (rawEvent.code) {
61             case REL_X:
62                 mRelX = rawEvent.value;
63                 break;
64             case REL_Y:
65                 mRelY = rawEvent.value;
66                 break;
67         }
68     }
69 }
70 
finishSync()71 void CursorMotionAccumulator::finishSync() {
72     clearRelativeAxes();
73 }
74 
75 // --- CursorInputMapper ---
76 
CursorInputMapper(InputDeviceContext & deviceContext,const InputReaderConfiguration & readerConfig)77 CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext,
78                                      const InputReaderConfiguration& readerConfig)
79       : InputMapper(deviceContext, readerConfig),
80         mLastEventTime(std::numeric_limits<nsecs_t>::min()),
81         mEnableNewMousePointerBallistics(input_flags::enable_new_mouse_pointer_ballistics()) {}
82 
getSources() const83 uint32_t CursorInputMapper::getSources() const {
84     return mSource;
85 }
86 
populateDeviceInfo(InputDeviceInfo & info)87 void CursorInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
88     InputMapper::populateDeviceInfo(info);
89 
90     if (mParameters.mode == Parameters::Mode::POINTER) {
91         if (!mBoundsInLogicalDisplay.isEmpty()) {
92             info.addMotionRange(AMOTION_EVENT_AXIS_X, mSource, mBoundsInLogicalDisplay.left,
93                                 mBoundsInLogicalDisplay.right, 0.0f, 0.0f, 0.0f);
94             info.addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, mBoundsInLogicalDisplay.top,
95                                 mBoundsInLogicalDisplay.bottom, 0.0f, 0.0f, 0.0f);
96         }
97     } else {
98         info.addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
99         info.addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
100         info.addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, mSource, -1.0f, 1.0f, 0.0f, mXScale,
101                             0.0f);
102         info.addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale,
103                             0.0f);
104     }
105     info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
106 
107     if (mCursorScrollAccumulator.haveRelativeVWheel()) {
108         info.addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
109     }
110     if (mCursorScrollAccumulator.haveRelativeHWheel()) {
111         info.addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
112     }
113 }
114 
dump(std::string & dump)115 void CursorInputMapper::dump(std::string& dump) {
116     dump += INDENT2 "Cursor Input Mapper:\n";
117     dumpParameters(dump);
118     dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
119     dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
120     dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
121     dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
122     dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
123                          toString(mCursorScrollAccumulator.haveRelativeVWheel()));
124     dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
125                          toString(mCursorScrollAccumulator.haveRelativeHWheel()));
126     dump += StringPrintf(INDENT3 "WheelYVelocityControlParameters: %s",
127                          mWheelYVelocityControl.getParameters().dump().c_str());
128     dump += StringPrintf(INDENT3 "WheelXVelocityControlParameters: %s",
129                          mWheelXVelocityControl.getParameters().dump().c_str());
130     dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
131     dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
132     dump += StringPrintf(INDENT3 "DisplayId: %s\n",
133                          toString(mDisplayId, streamableToString).c_str());
134     dump += StringPrintf(INDENT3 "Orientation: %s\n", ftl::enum_string(mOrientation).c_str());
135     dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
136     dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
137     dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
138 }
139 
reconfigure(nsecs_t when,const InputReaderConfiguration & readerConfig,ConfigurationChanges changes)140 std::list<NotifyArgs> CursorInputMapper::reconfigure(nsecs_t when,
141                                                      const InputReaderConfiguration& readerConfig,
142                                                      ConfigurationChanges changes) {
143     std::list<NotifyArgs> out = InputMapper::reconfigure(when, readerConfig, changes);
144 
145     if (!changes.any()) { // first time only
146         configureBasicParams();
147     }
148 
149     const bool configurePointerCapture = !changes.any() ||
150             (mParameters.mode != Parameters::Mode::NAVIGATION &&
151              changes.test(InputReaderConfiguration::Change::POINTER_CAPTURE));
152     if (configurePointerCapture) {
153         configureOnPointerCapture(readerConfig);
154         out.push_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId()));
155     }
156 
157     if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) ||
158         configurePointerCapture) {
159         configureOnChangeDisplayInfo(readerConfig);
160     }
161 
162     // Pointer speed settings depend on display settings.
163     if (!changes.any() || changes.test(InputReaderConfiguration::Change::POINTER_SPEED) ||
164         changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) || configurePointerCapture) {
165         configureOnChangePointerSpeed(readerConfig);
166     }
167     return out;
168 }
169 
computeParameters(const InputDeviceContext & deviceContext)170 CursorInputMapper::Parameters CursorInputMapper::computeParameters(
171         const InputDeviceContext& deviceContext) {
172     Parameters parameters;
173     parameters.mode = Parameters::Mode::POINTER;
174     const PropertyMap& config = deviceContext.getConfiguration();
175     std::optional<std::string> cursorModeString = config.getString("cursor.mode");
176     if (cursorModeString.has_value()) {
177         if (*cursorModeString == "navigation") {
178             parameters.mode = Parameters::Mode::NAVIGATION;
179         } else if (*cursorModeString != "pointer" && *cursorModeString != "default") {
180             ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString->c_str());
181         }
182     }
183 
184     parameters.orientationAware = config.getBool("cursor.orientationAware").value_or(false);
185 
186     parameters.hasAssociatedDisplay = false;
187     if (parameters.mode == Parameters::Mode::POINTER || parameters.orientationAware) {
188         parameters.hasAssociatedDisplay = true;
189     }
190     return parameters;
191 }
192 
dumpParameters(std::string & dump)193 void CursorInputMapper::dumpParameters(std::string& dump) {
194     dump += INDENT3 "Parameters:\n";
195     dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
196                          toString(mParameters.hasAssociatedDisplay));
197     dump += StringPrintf(INDENT4 "Mode: %s\n", ftl::enum_string(mParameters.mode).c_str());
198     dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
199 }
200 
reset(nsecs_t when)201 std::list<NotifyArgs> CursorInputMapper::reset(nsecs_t when) {
202     mButtonState = 0;
203     mDownTime = 0;
204     mLastEventTime = std::numeric_limits<nsecs_t>::min();
205 
206     mOldPointerVelocityControl.reset();
207     mNewPointerVelocityControl.reset();
208     mWheelXVelocityControl.reset();
209     mWheelYVelocityControl.reset();
210 
211     mCursorButtonAccumulator.reset(getDeviceContext());
212     mCursorMotionAccumulator.reset(getDeviceContext());
213     mCursorScrollAccumulator.reset(getDeviceContext());
214 
215     return InputMapper::reset(when);
216 }
217 
process(const RawEvent & rawEvent)218 std::list<NotifyArgs> CursorInputMapper::process(const RawEvent& rawEvent) {
219     std::list<NotifyArgs> out;
220     mCursorButtonAccumulator.process(rawEvent);
221     mCursorMotionAccumulator.process(rawEvent);
222     mCursorScrollAccumulator.process(rawEvent);
223 
224     if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) {
225         const auto [eventTime, readTime] =
226                 applyBluetoothTimestampSmoothening(getDeviceContext().getDeviceIdentifier(),
227                                                    rawEvent.when, rawEvent.readTime,
228                                                    mLastEventTime);
229         out += sync(eventTime, readTime);
230         mLastEventTime = eventTime;
231     }
232     return out;
233 }
234 
sync(nsecs_t when,nsecs_t readTime)235 std::list<NotifyArgs> CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
236     std::list<NotifyArgs> out;
237     if (!mDisplayId) {
238         // Ignore events when there is no target display configured.
239         return out;
240     }
241 
242     int32_t lastButtonState = mButtonState;
243     int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
244     mButtonState = currentButtonState;
245 
246     bool wasDown = isPointerDown(lastButtonState);
247     bool down = isPointerDown(currentButtonState);
248     bool downChanged;
249     if (!wasDown && down) {
250         mDownTime = when;
251         downChanged = true;
252     } else if (wasDown && !down) {
253         downChanged = true;
254     } else {
255         downChanged = false;
256     }
257     nsecs_t downTime = mDownTime;
258     bool buttonsChanged = currentButtonState != lastButtonState;
259     int32_t buttonsPressed = currentButtonState & ~lastButtonState;
260     int32_t buttonsReleased = lastButtonState & ~currentButtonState;
261 
262     float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
263     float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
264     bool moved = deltaX != 0 || deltaY != 0;
265 
266     // Rotate delta according to orientation.
267     rotateDelta(mOrientation, &deltaX, &deltaY);
268 
269     // Move the pointer.
270     PointerProperties pointerProperties;
271     pointerProperties.clear();
272     pointerProperties.id = 0;
273     pointerProperties.toolType = ToolType::MOUSE;
274 
275     PointerCoords pointerCoords;
276     pointerCoords.clear();
277 
278     float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
279     float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
280     bool scrolled = vscroll != 0 || hscroll != 0;
281 
282     mWheelYVelocityControl.move(when, nullptr, &vscroll);
283     mWheelXVelocityControl.move(when, &hscroll, nullptr);
284 
285     if (mEnableNewMousePointerBallistics) {
286         mNewPointerVelocityControl.move(when, &deltaX, &deltaY);
287     } else {
288         mOldPointerVelocityControl.move(when, &deltaX, &deltaY);
289     }
290 
291     float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
292     float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
293     if (mSource == AINPUT_SOURCE_MOUSE) {
294         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
295         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
296     } else {
297         // Pointer capture and navigation modes
298         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
299         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
300         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
301         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
302     }
303 
304     pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
305 
306     // Moving an external trackball or mouse should wake the device.
307     // We don't do this for internal cursor devices to prevent them from waking up
308     // the device in your pocket.
309     // TODO: Use the input device configuration to control this behavior more finely.
310     uint32_t policyFlags = 0;
311     if ((buttonsPressed || moved || scrolled) && getDeviceContext().isExternal()) {
312         policyFlags |= POLICY_FLAG_WAKE;
313     }
314 
315     // Synthesize key down from buttons if needed.
316     out += synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, readTime, getDeviceId(),
317                                 mSource, *mDisplayId, policyFlags, lastButtonState,
318                                 currentButtonState);
319 
320     // Send motion event.
321     if (downChanged || moved || scrolled || buttonsChanged) {
322         int32_t metaState = getContext()->getGlobalMetaState();
323         int32_t buttonState = lastButtonState;
324         int32_t motionEventAction;
325         if (downChanged) {
326             motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
327         } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
328             motionEventAction = AMOTION_EVENT_ACTION_MOVE;
329         } else {
330             motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
331         }
332 
333         if (buttonsReleased) {
334             BitSet32 released(buttonsReleased);
335             while (!released.isEmpty()) {
336                 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
337                 buttonState &= ~actionButton;
338                 out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime,
339                                                getDeviceId(), mSource, *mDisplayId, policyFlags,
340                                                AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
341                                                metaState, buttonState, MotionClassification::NONE,
342                                                AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
343                                                &pointerCoords, mXPrecision, mYPrecision,
344                                                xCursorPosition, yCursorPosition, downTime,
345                                                /*videoFrames=*/{}));
346             }
347         }
348 
349         out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
350                                        mSource, *mDisplayId, policyFlags, motionEventAction, 0, 0,
351                                        metaState, currentButtonState, MotionClassification::NONE,
352                                        AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
353                                        &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
354                                        yCursorPosition, downTime,
355                                        /*videoFrames=*/{}));
356 
357         if (buttonsPressed) {
358             BitSet32 pressed(buttonsPressed);
359             while (!pressed.isEmpty()) {
360                 int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
361                 buttonState |= actionButton;
362                 out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime,
363                                                getDeviceId(), mSource, *mDisplayId, policyFlags,
364                                                AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
365                                                metaState, buttonState, MotionClassification::NONE,
366                                                AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
367                                                &pointerCoords, mXPrecision, mYPrecision,
368                                                xCursorPosition, yCursorPosition, downTime,
369                                                /*videoFrames=*/{}));
370             }
371         }
372 
373         ALOG_ASSERT(buttonState == currentButtonState);
374 
375         // Send hover move after UP to tell the application that the mouse is hovering now.
376         if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) {
377             out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
378                                            mSource, *mDisplayId, policyFlags,
379                                            AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
380                                            currentButtonState, MotionClassification::NONE,
381                                            AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
382                                            &pointerCoords, mXPrecision, mYPrecision,
383                                            xCursorPosition, yCursorPosition, downTime,
384                                            /*videoFrames=*/{}));
385         }
386 
387         // Send scroll events.
388         if (scrolled) {
389             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
390             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
391 
392             out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
393                                            mSource, *mDisplayId, policyFlags,
394                                            AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
395                                            currentButtonState, MotionClassification::NONE,
396                                            AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
397                                            &pointerCoords, mXPrecision, mYPrecision,
398                                            xCursorPosition, yCursorPosition, downTime,
399                                            /*videoFrames=*/{}));
400         }
401     }
402 
403     // Synthesize key up from buttons if needed.
404     out += synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, readTime, getDeviceId(),
405                                 mSource, *mDisplayId, policyFlags, lastButtonState,
406                                 currentButtonState);
407 
408     mCursorMotionAccumulator.finishSync();
409     mCursorScrollAccumulator.finishSync();
410     return out;
411 }
412 
getScanCodeState(uint32_t sourceMask,int32_t scanCode)413 int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
414     if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
415         return getDeviceContext().getScanCodeState(scanCode);
416     } else {
417         return AKEY_STATE_UNKNOWN;
418     }
419 }
420 
getAssociatedDisplayId()421 std::optional<ui::LogicalDisplayId> CursorInputMapper::getAssociatedDisplayId() {
422     return mDisplayId;
423 }
424 
configureBasicParams()425 void CursorInputMapper::configureBasicParams() {
426     mCursorScrollAccumulator.configure(getDeviceContext());
427 
428     // Configure basic parameters.
429     mParameters = computeParameters(getDeviceContext());
430 
431     // Configure device mode.
432     switch (mParameters.mode) {
433         case Parameters::Mode::POINTER_RELATIVE:
434             // Should not happen during first time configuration.
435             ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
436             mParameters.mode = Parameters::Mode::POINTER;
437             [[fallthrough]];
438         case Parameters::Mode::POINTER:
439             mSource = AINPUT_SOURCE_MOUSE;
440             mXPrecision = 1.0f;
441             mYPrecision = 1.0f;
442             mXScale = 1.0f;
443             mYScale = 1.0f;
444             break;
445         case Parameters::Mode::NAVIGATION:
446             mSource = AINPUT_SOURCE_TRACKBALL;
447             mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
448             mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
449             mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
450             mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
451             break;
452     }
453 
454     mVWheelScale = 1.0f;
455     mHWheelScale = 1.0f;
456 }
457 
configureOnPointerCapture(const InputReaderConfiguration & config)458 void CursorInputMapper::configureOnPointerCapture(const InputReaderConfiguration& config) {
459     if (config.pointerCaptureRequest.isEnable()) {
460         if (mParameters.mode == Parameters::Mode::POINTER) {
461             mParameters.mode = Parameters::Mode::POINTER_RELATIVE;
462             mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
463         } else {
464             ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
465         }
466     } else {
467         if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
468             mParameters.mode = Parameters::Mode::POINTER;
469             mSource = AINPUT_SOURCE_MOUSE;
470         } else {
471             ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
472         }
473     }
474     bumpGeneration();
475 }
476 
configureOnChangePointerSpeed(const InputReaderConfiguration & config)477 void CursorInputMapper::configureOnChangePointerSpeed(const InputReaderConfiguration& config) {
478     if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
479         // Disable any acceleration or scaling for the pointer when Pointer Capture is enabled.
480         if (mEnableNewMousePointerBallistics) {
481             mNewPointerVelocityControl.setAccelerationEnabled(false);
482         } else {
483             mOldPointerVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
484         }
485         mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
486         mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
487     } else {
488         if (mEnableNewMousePointerBallistics) {
489             mNewPointerVelocityControl.setAccelerationEnabled(
490                     config.displaysWithMousePointerAccelerationDisabled.count(
491                             mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0);
492             mNewPointerVelocityControl.setCurve(
493                     createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed));
494         } else {
495             mOldPointerVelocityControl.setParameters(
496                     (config.displaysWithMousePointerAccelerationDisabled.count(
497                              mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0)
498                             ? config.pointerVelocityControlParameters
499                             : FLAT_VELOCITY_CONTROL_PARAMS);
500         }
501         mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters);
502         mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters);
503     }
504 }
505 
configureOnChangeDisplayInfo(const InputReaderConfiguration & config)506 void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfiguration& config) {
507     const bool isPointer = mParameters.mode == Parameters::Mode::POINTER;
508 
509     mDisplayId = ui::LogicalDisplayId::INVALID;
510     std::optional<DisplayViewport> resolvedViewport;
511     if (auto assocViewport = mDeviceContext.getAssociatedViewport(); assocViewport) {
512         // This InputDevice is associated with a viewport.
513         // Only generate events for the associated display.
514         mDisplayId = assocViewport->displayId;
515         resolvedViewport = *assocViewport;
516     } else if (isPointer) {
517         // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
518         // Always use DISPLAY_ID_NONE for mouse events.
519         // PointerChoreographer will make it target the correct the displayId later.
520         resolvedViewport = getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
521         mDisplayId =
522                 resolvedViewport ? std::make_optional(ui::LogicalDisplayId::INVALID) : std::nullopt;
523     }
524 
525     mOrientation = (mParameters.orientationAware && mParameters.hasAssociatedDisplay) ||
526                     mParameters.mode == Parameters::Mode::POINTER_RELATIVE || !resolvedViewport
527             ? ui::ROTATION_0
528             : getInverseRotation(resolvedViewport->orientation);
529 
530     mBoundsInLogicalDisplay = resolvedViewport
531             ? FloatRect{static_cast<float>(resolvedViewport->logicalLeft),
532                         static_cast<float>(resolvedViewport->logicalTop),
533                         static_cast<float>(resolvedViewport->logicalRight - 1),
534                         static_cast<float>(resolvedViewport->logicalBottom - 1)}
535             : FloatRect{0, 0, 0, 0};
536 
537     bumpGeneration();
538 }
539 
540 } // namespace android
541