• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "CursorButtonAccumulator.h"
24 #include "CursorScrollAccumulator.h"
25 #include "PointerControllerInterface.h"
26 #include "TouchCursorInputMapperCommon.h"
27 
28 #include "input/PrintTools.h"
29 
30 namespace android {
31 
32 // The default velocity control parameters that has no effect.
33 static const VelocityControlParameters FLAT_VELOCITY_CONTROL_PARAMS{};
34 
35 // --- CursorMotionAccumulator ---
36 
CursorMotionAccumulator()37 CursorMotionAccumulator::CursorMotionAccumulator() {
38     clearRelativeAxes();
39 }
40 
reset(InputDeviceContext & deviceContext)41 void CursorMotionAccumulator::reset(InputDeviceContext& deviceContext) {
42     clearRelativeAxes();
43 }
44 
clearRelativeAxes()45 void CursorMotionAccumulator::clearRelativeAxes() {
46     mRelX = 0;
47     mRelY = 0;
48 }
49 
process(const RawEvent * rawEvent)50 void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
51     if (rawEvent->type == EV_REL) {
52         switch (rawEvent->code) {
53             case REL_X:
54                 mRelX = rawEvent->value;
55                 break;
56             case REL_Y:
57                 mRelY = rawEvent->value;
58                 break;
59         }
60     }
61 }
62 
finishSync()63 void CursorMotionAccumulator::finishSync() {
64     clearRelativeAxes();
65 }
66 
67 // --- CursorInputMapper ---
68 
CursorInputMapper(InputDeviceContext & deviceContext)69 CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext)
70       : InputMapper(deviceContext) {}
71 
~CursorInputMapper()72 CursorInputMapper::~CursorInputMapper() {}
73 
getSources() const74 uint32_t CursorInputMapper::getSources() const {
75     return mSource;
76 }
77 
populateDeviceInfo(InputDeviceInfo * info)78 void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
79     InputMapper::populateDeviceInfo(info);
80 
81     if (mParameters.mode == Parameters::Mode::POINTER) {
82         float minX, minY, maxX, maxY;
83         if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
84             info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
85             info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
86         }
87     } else {
88         info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
89         info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
90         info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, mSource, -1.0f, 1.0f, 0.0f, mXScale,
91                              0.0f);
92         info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale,
93                              0.0f);
94     }
95     info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
96 
97     if (mCursorScrollAccumulator.haveRelativeVWheel()) {
98         info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
99     }
100     if (mCursorScrollAccumulator.haveRelativeHWheel()) {
101         info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
102     }
103 }
104 
dump(std::string & dump)105 void CursorInputMapper::dump(std::string& dump) {
106     dump += INDENT2 "Cursor Input Mapper:\n";
107     dumpParameters(dump);
108     dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
109     dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
110     dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
111     dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
112     dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
113                          toString(mCursorScrollAccumulator.haveRelativeVWheel()));
114     dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
115                          toString(mCursorScrollAccumulator.haveRelativeHWheel()));
116     dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
117     dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
118     dump += StringPrintf(INDENT3 "DisplayId: %s\n", toString(mDisplayId).c_str());
119     dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
120     dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
121     dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
122     dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
123 }
124 
configure(nsecs_t when,const InputReaderConfiguration * config,uint32_t changes)125 void CursorInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
126                                   uint32_t changes) {
127     InputMapper::configure(when, config, changes);
128 
129     if (!changes) { // first time only
130         mCursorScrollAccumulator.configure(getDeviceContext());
131 
132         // Configure basic parameters.
133         configureParameters();
134 
135         // Configure device mode.
136         switch (mParameters.mode) {
137             case Parameters::Mode::POINTER_RELATIVE:
138                 // Should not happen during first time configuration.
139                 ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
140                 mParameters.mode = Parameters::Mode::POINTER;
141                 [[fallthrough]];
142             case Parameters::Mode::POINTER:
143                 mSource = AINPUT_SOURCE_MOUSE;
144                 mXPrecision = 1.0f;
145                 mYPrecision = 1.0f;
146                 mXScale = 1.0f;
147                 mYScale = 1.0f;
148                 mPointerController = getContext()->getPointerController(getDeviceId());
149                 break;
150             case Parameters::Mode::NAVIGATION:
151                 mSource = AINPUT_SOURCE_TRACKBALL;
152                 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
153                 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
154                 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
155                 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
156                 break;
157         }
158 
159         mVWheelScale = 1.0f;
160         mHWheelScale = 1.0f;
161     }
162 
163     const bool configurePointerCapture = mParameters.mode != Parameters::Mode::NAVIGATION &&
164             ((!changes && config->pointerCaptureRequest.enable) ||
165              (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE));
166     if (configurePointerCapture) {
167         if (config->pointerCaptureRequest.enable) {
168             if (mParameters.mode == Parameters::Mode::POINTER) {
169                 mParameters.mode = Parameters::Mode::POINTER_RELATIVE;
170                 mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
171                 // Keep PointerController around in order to preserve the pointer position.
172                 mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
173             } else {
174                 ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
175             }
176         } else {
177             if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
178                 mParameters.mode = Parameters::Mode::POINTER;
179                 mSource = AINPUT_SOURCE_MOUSE;
180             } else {
181                 ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
182             }
183         }
184         bumpGeneration();
185         if (changes) {
186             NotifyDeviceResetArgs args(getContext()->getNextId(), when, getDeviceId());
187             getListener().notifyDeviceReset(&args);
188         }
189     }
190 
191     if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED) ||
192         configurePointerCapture) {
193         if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
194             // Disable any acceleration or scaling for the pointer when Pointer Capture is enabled.
195             mPointerVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
196             mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
197             mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
198         } else {
199             mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
200             mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
201             mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
202         }
203     }
204 
205     if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO) ||
206         configurePointerCapture) {
207         const bool isPointer = mParameters.mode == Parameters::Mode::POINTER;
208 
209         mDisplayId = ADISPLAY_ID_NONE;
210         if (auto viewport = mDeviceContext.getAssociatedViewport(); viewport) {
211             // This InputDevice is associated with a viewport.
212             // Only generate events for the associated display.
213             const bool mismatchedPointerDisplay =
214                     isPointer && (viewport->displayId != mPointerController->getDisplayId());
215             mDisplayId = mismatchedPointerDisplay ? std::nullopt
216                                                   : std::make_optional(viewport->displayId);
217         } else if (isPointer) {
218             // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
219             mDisplayId = mPointerController->getDisplayId();
220         }
221 
222         mOrientation = DISPLAY_ORIENTATION_0;
223         const bool isOrientedDevice =
224                 (mParameters.orientationAware && mParameters.hasAssociatedDisplay);
225         // InputReader works in the un-rotated display coordinate space, so we don't need to do
226         // anything if the device is already orientation-aware. If the device is not
227         // orientation-aware, then we need to apply the inverse rotation of the display so that
228         // when the display rotation is applied later as a part of the per-window transform, we
229         // get the expected screen coordinates. When pointer capture is enabled, we do not apply any
230         // rotations and report values directly from the input device.
231         if (!isOrientedDevice && mDisplayId &&
232             mParameters.mode != Parameters::Mode::POINTER_RELATIVE) {
233             if (auto viewport = config->getDisplayViewportById(*mDisplayId); viewport) {
234                 mOrientation = getInverseRotation(viewport->orientation);
235             }
236         }
237 
238         bumpGeneration();
239     }
240 }
241 
configureParameters()242 void CursorInputMapper::configureParameters() {
243     mParameters.mode = Parameters::Mode::POINTER;
244     String8 cursorModeString;
245     if (getDeviceContext().getConfiguration().tryGetProperty(String8("cursor.mode"),
246                                                              cursorModeString)) {
247         if (cursorModeString == "navigation") {
248             mParameters.mode = Parameters::Mode::NAVIGATION;
249         } else if (cursorModeString != "pointer" && cursorModeString != "default") {
250             ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
251         }
252     }
253 
254     mParameters.orientationAware = false;
255     getDeviceContext().getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
256                                                          mParameters.orientationAware);
257 
258     mParameters.hasAssociatedDisplay = false;
259     if (mParameters.mode == Parameters::Mode::POINTER || mParameters.orientationAware) {
260         mParameters.hasAssociatedDisplay = true;
261     }
262 }
263 
dumpParameters(std::string & dump)264 void CursorInputMapper::dumpParameters(std::string& dump) {
265     dump += INDENT3 "Parameters:\n";
266     dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
267                          toString(mParameters.hasAssociatedDisplay));
268     dump += StringPrintf(INDENT4 "Mode: %s\n", ftl::enum_string(mParameters.mode).c_str());
269     dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
270 }
271 
reset(nsecs_t when)272 void CursorInputMapper::reset(nsecs_t when) {
273     mButtonState = 0;
274     mDownTime = 0;
275 
276     mPointerVelocityControl.reset();
277     mWheelXVelocityControl.reset();
278     mWheelYVelocityControl.reset();
279 
280     mCursorButtonAccumulator.reset(getDeviceContext());
281     mCursorMotionAccumulator.reset(getDeviceContext());
282     mCursorScrollAccumulator.reset(getDeviceContext());
283 
284     InputMapper::reset(when);
285 }
286 
process(const RawEvent * rawEvent)287 void CursorInputMapper::process(const RawEvent* rawEvent) {
288     mCursorButtonAccumulator.process(rawEvent);
289     mCursorMotionAccumulator.process(rawEvent);
290     mCursorScrollAccumulator.process(rawEvent);
291 
292     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
293         sync(rawEvent->when, rawEvent->readTime);
294     }
295 }
296 
sync(nsecs_t when,nsecs_t readTime)297 void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
298     if (!mDisplayId) {
299         // Ignore events when there is no target display configured.
300         return;
301     }
302 
303     int32_t lastButtonState = mButtonState;
304     int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
305     mButtonState = currentButtonState;
306 
307     bool wasDown = isPointerDown(lastButtonState);
308     bool down = isPointerDown(currentButtonState);
309     bool downChanged;
310     if (!wasDown && down) {
311         mDownTime = when;
312         downChanged = true;
313     } else if (wasDown && !down) {
314         downChanged = true;
315     } else {
316         downChanged = false;
317     }
318     nsecs_t downTime = mDownTime;
319     bool buttonsChanged = currentButtonState != lastButtonState;
320     int32_t buttonsPressed = currentButtonState & ~lastButtonState;
321     int32_t buttonsReleased = lastButtonState & ~currentButtonState;
322 
323     float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
324     float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
325     bool moved = deltaX != 0 || deltaY != 0;
326 
327     // Rotate delta according to orientation.
328     rotateDelta(mOrientation, &deltaX, &deltaY);
329 
330     // Move the pointer.
331     PointerProperties pointerProperties;
332     pointerProperties.clear();
333     pointerProperties.id = 0;
334     pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
335 
336     PointerCoords pointerCoords;
337     pointerCoords.clear();
338 
339     float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
340     float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
341     bool scrolled = vscroll != 0 || hscroll != 0;
342 
343     mWheelYVelocityControl.move(when, nullptr, &vscroll);
344     mWheelXVelocityControl.move(when, &hscroll, nullptr);
345 
346     mPointerVelocityControl.move(when, &deltaX, &deltaY);
347 
348     float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
349     float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
350     if (mSource == AINPUT_SOURCE_MOUSE) {
351         if (moved || scrolled || buttonsChanged) {
352             mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
353 
354             if (moved) {
355                 mPointerController->move(deltaX, deltaY);
356             }
357 
358             if (buttonsChanged) {
359                 mPointerController->setButtonState(currentButtonState);
360             }
361 
362             mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
363         }
364 
365         mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
366 
367         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
368         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
369         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
370         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
371     } else {
372         // Pointer capture and navigation modes
373         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
374         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
375         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
376         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
377     }
378 
379     pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
380 
381     // Moving an external trackball or mouse should wake the device.
382     // We don't do this for internal cursor devices to prevent them from waking up
383     // the device in your pocket.
384     // TODO: Use the input device configuration to control this behavior more finely.
385     uint32_t policyFlags = 0;
386     if ((buttonsPressed || moved || scrolled) && getDeviceContext().isExternal()) {
387         policyFlags |= POLICY_FLAG_WAKE;
388     }
389 
390     // Synthesize key down from buttons if needed.
391     synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, readTime, getDeviceId(),
392                          mSource, *mDisplayId, policyFlags, lastButtonState, currentButtonState);
393 
394     // Send motion event.
395     if (downChanged || moved || scrolled || buttonsChanged) {
396         int32_t metaState = getContext()->getGlobalMetaState();
397         int32_t buttonState = lastButtonState;
398         int32_t motionEventAction;
399         if (downChanged) {
400             motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
401         } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
402             motionEventAction = AMOTION_EVENT_ACTION_MOVE;
403         } else {
404             motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
405         }
406 
407         if (buttonsReleased) {
408             BitSet32 released(buttonsReleased);
409             while (!released.isEmpty()) {
410                 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
411                 buttonState &= ~actionButton;
412                 NotifyMotionArgs releaseArgs(getContext()->getNextId(), when, readTime,
413                                              getDeviceId(), mSource, *mDisplayId, policyFlags,
414                                              AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
415                                              metaState, buttonState, MotionClassification::NONE,
416                                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
417                                              &pointerCoords, mXPrecision, mYPrecision,
418                                              xCursorPosition, yCursorPosition, downTime,
419                                              /* videoFrames */ {});
420                 getListener().notifyMotion(&releaseArgs);
421             }
422         }
423 
424         NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
425                               *mDisplayId, policyFlags, motionEventAction, 0, 0, metaState,
426                               currentButtonState, MotionClassification::NONE,
427                               AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
428                               mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime,
429                               /* videoFrames */ {});
430         getListener().notifyMotion(&args);
431 
432         if (buttonsPressed) {
433             BitSet32 pressed(buttonsPressed);
434             while (!pressed.isEmpty()) {
435                 int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
436                 buttonState |= actionButton;
437                 NotifyMotionArgs pressArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
438                                            mSource, *mDisplayId, policyFlags,
439                                            AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
440                                            metaState, buttonState, MotionClassification::NONE,
441                                            AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
442                                            &pointerCoords, mXPrecision, mYPrecision,
443                                            xCursorPosition, yCursorPosition, downTime,
444                                            /* videoFrames */ {});
445                 getListener().notifyMotion(&pressArgs);
446             }
447         }
448 
449         ALOG_ASSERT(buttonState == currentButtonState);
450 
451         // Send hover move after UP to tell the application that the mouse is hovering now.
452         if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) {
453             NotifyMotionArgs hoverArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
454                                        mSource, *mDisplayId, policyFlags,
455                                        AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
456                                        currentButtonState, MotionClassification::NONE,
457                                        AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
458                                        &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
459                                        yCursorPosition, downTime, /* videoFrames */ {});
460             getListener().notifyMotion(&hoverArgs);
461         }
462 
463         // Send scroll events.
464         if (scrolled) {
465             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
466             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
467 
468             NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
469                                         mSource, *mDisplayId, policyFlags,
470                                         AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
471                                         currentButtonState, MotionClassification::NONE,
472                                         AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
473                                         &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
474                                         yCursorPosition, downTime, /* videoFrames */ {});
475             getListener().notifyMotion(&scrollArgs);
476         }
477     }
478 
479     // Synthesize key up from buttons if needed.
480     synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, readTime, getDeviceId(), mSource,
481                          *mDisplayId, policyFlags, lastButtonState, currentButtonState);
482 
483     mCursorMotionAccumulator.finishSync();
484     mCursorScrollAccumulator.finishSync();
485 }
486 
getScanCodeState(uint32_t sourceMask,int32_t scanCode)487 int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
488     if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
489         return getDeviceContext().getScanCodeState(scanCode);
490     } else {
491         return AKEY_STATE_UNKNOWN;
492     }
493 }
494 
getAssociatedDisplayId()495 std::optional<int32_t> CursorInputMapper::getAssociatedDisplayId() {
496     return mDisplayId;
497 }
498 
499 } // namespace android
500