• 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 "TouchInputMapper.h"
22 
23 #include <ftl/enum.h>
24 #include <input/PrintTools.h>
25 
26 #include "CursorButtonAccumulator.h"
27 #include "CursorScrollAccumulator.h"
28 #include "TouchButtonAccumulator.h"
29 #include "TouchCursorInputMapperCommon.h"
30 #include "ui/Rotation.h"
31 
32 namespace android {
33 
34 // --- Constants ---
35 
36 // Artificial latency on synthetic events created from stylus data without corresponding touch
37 // data.
38 static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
39 
40 // Minimum width between two pointers to determine a gesture as freeform gesture in mm
41 static const float MIN_FREEFORM_GESTURE_WIDTH_IN_MILLIMETER = 30;
42 // --- Static Definitions ---
43 
44 static const DisplayViewport kUninitializedViewport;
45 
toString(const Rect & rect)46 static std::string toString(const Rect& rect) {
47     return base::StringPrintf("Rect{%d, %d, %d, %d}", rect.left, rect.top, rect.right, rect.bottom);
48 }
49 
toString(const ui::Size & size)50 static std::string toString(const ui::Size& size) {
51     return base::StringPrintf("%dx%d", size.width, size.height);
52 }
53 
isPointInRect(const Rect & rect,vec2 p)54 static bool isPointInRect(const Rect& rect, vec2 p) {
55     return p.x >= rect.left && p.x < rect.right && p.y >= rect.top && p.y < rect.bottom;
56 }
57 
toString(const InputDeviceUsiVersion & v)58 static std::string toString(const InputDeviceUsiVersion& v) {
59     return base::StringPrintf("%d.%d", v.majorVersion, v.minorVersion);
60 }
61 
62 template <typename T>
swap(T & a,T & b)63 inline static void swap(T& a, T& b) {
64     T temp = a;
65     a = b;
66     b = temp;
67 }
68 
calculateCommonVector(float a,float b)69 static float calculateCommonVector(float a, float b) {
70     if (a > 0 && b > 0) {
71         return a < b ? a : b;
72     } else if (a < 0 && b < 0) {
73         return a > b ? a : b;
74     } else {
75         return 0;
76     }
77 }
78 
distance(float x1,float y1,float x2,float y2)79 inline static float distance(float x1, float y1, float x2, float y2) {
80     return hypotf(x1 - x2, y1 - y2);
81 }
82 
signExtendNybble(int32_t value)83 inline static int32_t signExtendNybble(int32_t value) {
84     return value >= 8 ? value - 16 : value;
85 }
86 
getNaturalDisplaySize(const DisplayViewport & viewport)87 static ui::Size getNaturalDisplaySize(const DisplayViewport& viewport) {
88     ui::Size rotatedDisplaySize{viewport.deviceWidth, viewport.deviceHeight};
89     if (viewport.orientation == ui::ROTATION_90 || viewport.orientation == ui::ROTATION_270) {
90         std::swap(rotatedDisplaySize.width, rotatedDisplaySize.height);
91     }
92     return rotatedDisplaySize;
93 }
94 
filterButtonState(InputReaderConfiguration & config,int32_t buttonState)95 static int32_t filterButtonState(InputReaderConfiguration& config, int32_t buttonState) {
96     if (!config.stylusButtonMotionEventsEnabled) {
97         buttonState &=
98                 ~(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY | AMOTION_EVENT_BUTTON_STYLUS_SECONDARY);
99     }
100     return buttonState;
101 }
102 
103 // --- RawPointerData ---
104 
getCentroidOfTouchingPointers(float * outX,float * outY) const105 void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
106     float x = 0, y = 0;
107     uint32_t count = touchingIdBits.count();
108     if (count) {
109         for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty();) {
110             uint32_t id = idBits.clearFirstMarkedBit();
111             const Pointer& pointer = pointerForId(id);
112             x += pointer.x;
113             y += pointer.y;
114         }
115         x /= count;
116         y /= count;
117     }
118     *outX = x;
119     *outY = y;
120 }
121 
122 // --- TouchInputMapper ---
123 
TouchInputMapper(InputDeviceContext & deviceContext,const InputReaderConfiguration & readerConfig)124 TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext,
125                                    const InputReaderConfiguration& readerConfig)
126       : InputMapper(deviceContext, readerConfig),
127         mTouchButtonAccumulator(deviceContext),
128         mConfig(readerConfig) {}
129 
~TouchInputMapper()130 TouchInputMapper::~TouchInputMapper() {}
131 
getSources() const132 uint32_t TouchInputMapper::getSources() const {
133     // The SOURCE_BLUETOOTH_STYLUS is added to events dynamically if the current stream is modified
134     // by the external stylus state. That's why we don't add it directly to mSource during
135     // configuration.
136     return mSource | (hasExternalStylus() ? AINPUT_SOURCE_BLUETOOTH_STYLUS : 0);
137 }
138 
populateDeviceInfo(InputDeviceInfo & info)139 void TouchInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
140     InputMapper::populateDeviceInfo(info);
141 
142     if (mDeviceMode == DeviceMode::DISABLED) {
143         return;
144     }
145 
146     info.addMotionRange(mOrientedRanges.x);
147     info.addMotionRange(mOrientedRanges.y);
148     info.addMotionRange(mOrientedRanges.pressure);
149 
150     if (mDeviceMode == DeviceMode::UNSCALED && mSource == AINPUT_SOURCE_TOUCHPAD) {
151         // Populate RELATIVE_X and RELATIVE_Y motion ranges for touchpad capture mode.
152         //
153         // RELATIVE_X and RELATIVE_Y motion ranges should be the largest possible relative
154         // motion, i.e. the hardware dimensions, as the finger could move completely across the
155         // touchpad in one sample cycle.
156         const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
157         const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
158         info.addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, mSource, -x.max, x.max, x.flat, x.fuzz,
159                             x.resolution);
160         info.addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, mSource, -y.max, y.max, y.flat, y.fuzz,
161                             y.resolution);
162     }
163 
164     if (mOrientedRanges.size) {
165         info.addMotionRange(*mOrientedRanges.size);
166     }
167 
168     if (mOrientedRanges.touchMajor) {
169         info.addMotionRange(*mOrientedRanges.touchMajor);
170         info.addMotionRange(*mOrientedRanges.touchMinor);
171     }
172 
173     if (mOrientedRanges.toolMajor) {
174         info.addMotionRange(*mOrientedRanges.toolMajor);
175         info.addMotionRange(*mOrientedRanges.toolMinor);
176     }
177 
178     if (mOrientedRanges.orientation) {
179         info.addMotionRange(*mOrientedRanges.orientation);
180     }
181 
182     if (mOrientedRanges.distance) {
183         info.addMotionRange(*mOrientedRanges.distance);
184     }
185 
186     if (mOrientedRanges.tilt) {
187         info.addMotionRange(*mOrientedRanges.tilt);
188     }
189 
190     if (mCursorScrollAccumulator.haveRelativeVWheel()) {
191         info.addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
192     }
193     if (mCursorScrollAccumulator.haveRelativeHWheel()) {
194         info.addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
195     }
196     info.setButtonUnderPad(mParameters.hasButtonUnderPad);
197     info.setUsiVersion(mParameters.usiVersion);
198 }
199 
dump(std::string & dump)200 void TouchInputMapper::dump(std::string& dump) {
201     dump += StringPrintf(INDENT2 "Touch Input Mapper (mode - %s):\n",
202                          ftl::enum_string(mDeviceMode).c_str());
203     dumpParameters(dump);
204     dumpVirtualKeys(dump);
205     dumpRawPointerAxes(dump);
206     dumpCalibration(dump);
207     dumpAffineTransformation(dump);
208     dumpDisplay(dump);
209 
210     dump += StringPrintf(INDENT3 "Translation and Scaling Factors:\n");
211     mRawToDisplay.dump(dump, "RawToDisplay Transform:", INDENT4);
212     mRawRotation.dump(dump, "RawRotation Transform:", INDENT4);
213     dump += StringPrintf(INDENT4 "OrientedXPrecision: %0.3f\n", mOrientedXPrecision);
214     dump += StringPrintf(INDENT4 "OrientedYPrecision: %0.3f\n", mOrientedYPrecision);
215     dump += StringPrintf(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
216     dump += StringPrintf(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
217     dump += StringPrintf(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
218     dump += StringPrintf(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
219     dump += StringPrintf(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
220     dump += StringPrintf(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
221     dump += StringPrintf(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
222     dump += StringPrintf(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
223     dump += StringPrintf(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
224     dump += StringPrintf(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
225 
226     dump += StringPrintf(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState);
227     dump += StringPrintf(INDENT3 "Last Raw Touch: pointerCount=%d\n",
228                          mLastRawState.rawPointerData.pointerCount);
229     for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
230         const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
231         dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
232                                      "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
233                                      "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
234                                      "toolType=%s, isHovering=%s\n",
235                              i, pointer.id, pointer.x, pointer.y, pointer.pressure,
236                              pointer.touchMajor, pointer.touchMinor, pointer.toolMajor,
237                              pointer.toolMinor, pointer.orientation, pointer.tiltX, pointer.tiltY,
238                              pointer.distance, ftl::enum_string(pointer.toolType).c_str(),
239                              toString(pointer.isHovering));
240     }
241 
242     dump += StringPrintf(INDENT3 "Last Cooked Button State: 0x%08x\n",
243                          mLastCookedState.buttonState);
244     dump += StringPrintf(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
245                          mLastCookedState.cookedPointerData.pointerCount);
246     for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
247         const PointerProperties& pointerProperties =
248                 mLastCookedState.cookedPointerData.pointerProperties[i];
249         const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
250         dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, dx=%0.3f, dy=%0.3f, "
251                                      "pressure=%0.3f, touchMajor=%0.3f, touchMinor=%0.3f, "
252                                      "toolMajor=%0.3f, toolMinor=%0.3f, "
253                                      "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
254                                      "toolType=%s, isHovering=%s\n",
255                              i, pointerProperties.id, pointerCoords.getX(), pointerCoords.getY(),
256                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
257                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y),
258                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
259                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
260                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
261                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
262                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
263                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
264                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
265                              pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
266                              ftl::enum_string(pointerProperties.toolType).c_str(),
267                              toString(mLastCookedState.cookedPointerData.isHovering(i)));
268     }
269 
270     dump += INDENT3 "Stylus Fusion:\n";
271     dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n",
272                          toString(mExternalStylusConnected));
273     dump += StringPrintf(INDENT4 "Fused External Stylus Pointer ID: %s\n",
274                          toString(mFusedStylusPointerId).c_str());
275     dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
276                          mExternalStylusFusionTimeout);
277     dump += StringPrintf(INDENT4 " External Stylus Buttons Applied: 0x%08x",
278                          mExternalStylusButtonsApplied);
279     dump += INDENT3 "External Stylus State:\n";
280     dumpStylusState(dump, mExternalStylusState);
281 
282     if (mDeviceMode == DeviceMode::POINTER) {
283         dump += StringPrintf(INDENT3 "Pointer Gesture Detector:\n");
284         dump += StringPrintf(INDENT4 "XMovementScale: %0.3f\n", mPointerXMovementScale);
285         dump += StringPrintf(INDENT4 "YMovementScale: %0.3f\n", mPointerYMovementScale);
286         dump += StringPrintf(INDENT4 "XZoomScale: %0.3f\n", mPointerXZoomScale);
287         dump += StringPrintf(INDENT4 "YZoomScale: %0.3f\n", mPointerYZoomScale);
288         dump += StringPrintf(INDENT4 "MaxSwipeWidth: %f\n", mPointerGestureMaxSwipeWidth);
289     }
290 }
291 
reconfigure(nsecs_t when,const InputReaderConfiguration & config,ConfigurationChanges changes)292 std::list<NotifyArgs> TouchInputMapper::reconfigure(nsecs_t when,
293                                                     const InputReaderConfiguration& config,
294                                                     ConfigurationChanges changes) {
295     std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
296 
297     mConfig = config;
298 
299     // Full configuration should happen the first time configure is called and
300     // when the device type is changed. Changing a device type can affect
301     // various other parameters so should result in a reconfiguration.
302     if (!changes.any() || changes.test(InputReaderConfiguration::Change::DEVICE_TYPE)) {
303         // Configure basic parameters.
304         mParameters = computeParameters(getDeviceContext());
305 
306         // Configure common accumulators.
307         mCursorScrollAccumulator.configure(getDeviceContext());
308         mTouchButtonAccumulator.configure();
309 
310         // Configure absolute axis information.
311         configureRawPointerAxes();
312 
313         // Prepare input device calibration.
314         parseCalibration();
315         resolveCalibration();
316     }
317 
318     if (!changes.any() ||
319         changes.test(InputReaderConfiguration::Change::TOUCH_AFFINE_TRANSFORMATION)) {
320         // Update location calibration to reflect current settings
321         updateAffineTransformation();
322     }
323 
324     if (!changes.any() || changes.test(InputReaderConfiguration::Change::POINTER_SPEED)) {
325         // Update pointer speed.
326         mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
327         mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
328         mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
329     }
330 
331     using namespace ftl::flag_operators;
332     bool resetNeeded = false;
333     if (!changes.any() ||
334         changes.any(InputReaderConfiguration::Change::DISPLAY_INFO |
335                     InputReaderConfiguration::Change::POINTER_CAPTURE |
336                     InputReaderConfiguration::Change::POINTER_GESTURE_ENABLEMENT |
337                     InputReaderConfiguration::Change::SHOW_TOUCHES |
338                     InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE |
339                     InputReaderConfiguration::Change::DEVICE_TYPE)) {
340         // Configure device sources, display dimensions, orientation and
341         // scaling factors.
342         configureInputDevice(when, &resetNeeded);
343     }
344 
345     if (changes.any() && resetNeeded) {
346         out += reset(when);
347 
348         // Send reset, unless this is the first time the device has been configured,
349         // in which case the reader will call reset itself after all mappers are ready.
350         out.emplace_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId()));
351     }
352     return out;
353 }
354 
resolveExternalStylusPresence()355 void TouchInputMapper::resolveExternalStylusPresence() {
356     std::vector<InputDeviceInfo> devices;
357     getContext()->getExternalStylusDevices(devices);
358     mExternalStylusConnected = !devices.empty();
359 
360     if (!mExternalStylusConnected) {
361         resetExternalStylus();
362     }
363 }
364 
computeParameters(const InputDeviceContext & deviceContext)365 TouchInputMapper::Parameters TouchInputMapper::computeParameters(
366         const InputDeviceContext& deviceContext) {
367     Parameters parameters;
368     // Use the pointer presentation mode for devices that do not support distinct
369     // multitouch.  The spot-based presentation relies on being able to accurately
370     // locate two or more fingers on the touch pad.
371     parameters.gestureMode = deviceContext.hasInputProperty(INPUT_PROP_SEMI_MT)
372             ? Parameters::GestureMode::SINGLE_TOUCH
373             : Parameters::GestureMode::MULTI_TOUCH;
374 
375     const PropertyMap& config = deviceContext.getConfiguration();
376     std::optional<std::string> gestureModeString = config.getString("touch.gestureMode");
377     if (gestureModeString.has_value()) {
378         if (*gestureModeString == "single-touch") {
379             parameters.gestureMode = Parameters::GestureMode::SINGLE_TOUCH;
380         } else if (*gestureModeString == "multi-touch") {
381             parameters.gestureMode = Parameters::GestureMode::MULTI_TOUCH;
382         } else if (*gestureModeString != "default") {
383             ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString->c_str());
384         }
385     }
386 
387     parameters.deviceType = computeDeviceType(deviceContext);
388 
389     parameters.hasButtonUnderPad = deviceContext.hasInputProperty(INPUT_PROP_BUTTONPAD);
390 
391     parameters.orientationAware =
392             config.getBool("touch.orientationAware")
393                     .value_or(parameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN);
394 
395     parameters.orientation = ui::ROTATION_0;
396     std::optional<std::string> orientationString = config.getString("touch.orientation");
397     if (orientationString.has_value()) {
398         if (parameters.deviceType != Parameters::DeviceType::TOUCH_SCREEN) {
399             ALOGW("The configuration 'touch.orientation' is only supported for touchscreens.");
400         } else if (*orientationString == "ORIENTATION_90") {
401             parameters.orientation = ui::ROTATION_90;
402         } else if (*orientationString == "ORIENTATION_180") {
403             parameters.orientation = ui::ROTATION_180;
404         } else if (*orientationString == "ORIENTATION_270") {
405             parameters.orientation = ui::ROTATION_270;
406         } else if (*orientationString != "ORIENTATION_0") {
407             ALOGW("Invalid value for touch.orientation: '%s'", orientationString->c_str());
408         }
409     }
410 
411     parameters.hasAssociatedDisplay = false;
412     parameters.associatedDisplayIsExternal = false;
413     if (parameters.orientationAware ||
414         parameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN ||
415         parameters.deviceType == Parameters::DeviceType::POINTER ||
416         (parameters.deviceType == Parameters::DeviceType::TOUCH_NAVIGATION &&
417          deviceContext.getAssociatedViewport())) {
418         parameters.hasAssociatedDisplay = true;
419         if (parameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN) {
420             parameters.associatedDisplayIsExternal = deviceContext.isExternal();
421             parameters.uniqueDisplayId = config.getString("touch.displayId").value_or("").c_str();
422         }
423     }
424     if (deviceContext.getAssociatedDisplayPort()) {
425         parameters.hasAssociatedDisplay = true;
426     }
427 
428     // Initial downs on external touch devices should wake the device.
429     // Normally we don't do this for internal touch screens to prevent them from waking
430     // up in your pocket but you can enable it using the input device configuration.
431     parameters.wake = config.getBool("touch.wake").value_or(deviceContext.isExternal());
432 
433     std::optional<int32_t> usiVersionMajor = config.getInt("touch.usiVersionMajor");
434     std::optional<int32_t> usiVersionMinor = config.getInt("touch.usiVersionMinor");
435     if (usiVersionMajor.has_value() && usiVersionMinor.has_value()) {
436         parameters.usiVersion = {
437                 .majorVersion = *usiVersionMajor,
438                 .minorVersion = *usiVersionMinor,
439         };
440     }
441 
442     parameters.enableForInactiveViewport =
443             config.getBool("touch.enableForInactiveViewport").value_or(false);
444 
445     return parameters;
446 }
447 
computeDeviceType(const InputDeviceContext & deviceContext)448 TouchInputMapper::Parameters::DeviceType TouchInputMapper::computeDeviceType(
449         const InputDeviceContext& deviceContext) {
450     Parameters::DeviceType deviceType;
451     if (deviceContext.hasInputProperty(INPUT_PROP_DIRECT)) {
452         // The device is a touch screen.
453         deviceType = Parameters::DeviceType::TOUCH_SCREEN;
454     } else if (deviceContext.hasInputProperty(INPUT_PROP_POINTER)) {
455         // The device is a pointing device like a track pad.
456         deviceType = Parameters::DeviceType::POINTER;
457     } else {
458         // The device is a touch pad of unknown purpose.
459         deviceType = Parameters::DeviceType::POINTER;
460     }
461 
462     // Type association takes precedence over the device type found in the idc file.
463     std::string deviceTypeString = deviceContext.getDeviceTypeAssociation().value_or("");
464     if (deviceTypeString.empty()) {
465         deviceTypeString =
466                 deviceContext.getConfiguration().getString("touch.deviceType").value_or("");
467     }
468     if (deviceTypeString == "touchScreen") {
469         deviceType = Parameters::DeviceType::TOUCH_SCREEN;
470     } else if (deviceTypeString == "touchNavigation") {
471         deviceType = Parameters::DeviceType::TOUCH_NAVIGATION;
472     } else if (deviceTypeString == "pointer") {
473         deviceType = Parameters::DeviceType::POINTER;
474     } else if (deviceTypeString != "default" && deviceTypeString != "") {
475         ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.c_str());
476     }
477     return deviceType;
478 }
479 
dumpParameters(std::string & dump)480 void TouchInputMapper::dumpParameters(std::string& dump) {
481     dump += INDENT3 "Parameters:\n";
482 
483     dump += INDENT4 "GestureMode: " + ftl::enum_string(mParameters.gestureMode) + "\n";
484 
485     dump += INDENT4 "DeviceType: " + ftl::enum_string(mParameters.deviceType) + "\n";
486 
487     dump += StringPrintf(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, "
488                                  "displayId='%s'\n",
489                          toString(mParameters.hasAssociatedDisplay),
490                          toString(mParameters.associatedDisplayIsExternal),
491                          mParameters.uniqueDisplayId.c_str());
492     dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
493     dump += INDENT4 "Orientation: " + ftl::enum_string(mParameters.orientation) + "\n";
494     dump += StringPrintf(INDENT4 "UsiVersion: %s\n",
495                          toString(mParameters.usiVersion, toString).c_str());
496     dump += StringPrintf(INDENT4 "EnableForInactiveViewport: %s\n",
497                          toString(mParameters.enableForInactiveViewport));
498 }
499 
configureRawPointerAxes()500 void TouchInputMapper::configureRawPointerAxes() {
501     mRawPointerAxes.clear();
502 }
503 
dumpRawPointerAxes(std::string & dump)504 void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
505     dump += INDENT3 "Raw Touch Axes:\n";
506     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
507     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
508     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
509     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
510     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
511     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
512     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
513     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
514     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
515     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
516     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
517     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
518     dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
519 }
520 
hasExternalStylus() const521 bool TouchInputMapper::hasExternalStylus() const {
522     return mExternalStylusConnected;
523 }
524 
525 /**
526  * Determine which DisplayViewport to use.
527  * 1. If a device has associated display, get the matching viewport.
528  * 2. Always use the suggested viewport from WindowManagerService for pointers.
529  * 3. Get the matching viewport by either unique id in idc file or by the display type
530  * (internal or external).
531  * 4. Otherwise, use a non-display viewport.
532  */
findViewport()533 std::optional<DisplayViewport> TouchInputMapper::findViewport() {
534     if (mParameters.hasAssociatedDisplay && mDeviceMode != DeviceMode::UNSCALED) {
535         if (getDeviceContext().getAssociatedViewport()) {
536             return getDeviceContext().getAssociatedViewport();
537         }
538 
539         const std::optional<std::string> associatedDisplayUniqueId =
540                 getDeviceContext().getAssociatedDisplayUniqueId();
541         if (associatedDisplayUniqueId) {
542             return getDeviceContext().getAssociatedViewport();
543         }
544 
545         if (mDeviceMode == DeviceMode::POINTER) {
546             std::optional<DisplayViewport> viewport =
547                     mConfig.getDisplayViewportById(mConfig.defaultPointerDisplayId);
548             if (viewport) {
549                 return viewport;
550             } else {
551                 ALOGW("Can't find designated display viewport with ID %" PRId32 " for pointers.",
552                       mConfig.defaultPointerDisplayId);
553             }
554         }
555 
556         // Check if uniqueDisplayId is specified in idc file.
557         if (!mParameters.uniqueDisplayId.empty()) {
558             return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
559         }
560 
561         ViewportType viewportTypeToUse;
562         if (mParameters.associatedDisplayIsExternal) {
563             viewportTypeToUse = ViewportType::EXTERNAL;
564         } else {
565             viewportTypeToUse = ViewportType::INTERNAL;
566         }
567 
568         std::optional<DisplayViewport> viewport =
569                 mConfig.getDisplayViewportByType(viewportTypeToUse);
570         if (!viewport && viewportTypeToUse == ViewportType::EXTERNAL) {
571             ALOGW("Input device %s should be associated with external display, "
572                   "fallback to internal one for the external viewport is not found.",
573                   getDeviceName().c_str());
574             viewport = mConfig.getDisplayViewportByType(ViewportType::INTERNAL);
575         }
576 
577         return viewport;
578     }
579 
580     // No associated display, return a non-display viewport.
581     DisplayViewport newViewport;
582     // Raw width and height in the natural orientation.
583     int32_t rawWidth = mRawPointerAxes.getRawWidth();
584     int32_t rawHeight = mRawPointerAxes.getRawHeight();
585     newViewport.setNonDisplayViewport(rawWidth, rawHeight);
586     return std::make_optional(newViewport);
587 }
588 
clampResolution(const char * axisName,int32_t resolution) const589 int32_t TouchInputMapper::clampResolution(const char* axisName, int32_t resolution) const {
590     if (resolution < 0) {
591         ALOGE("Invalid %s resolution %" PRId32 " for device %s", axisName, resolution,
592               getDeviceName().c_str());
593         return 0;
594     }
595     return resolution;
596 }
597 
initializeSizeRanges()598 void TouchInputMapper::initializeSizeRanges() {
599     if (mCalibration.sizeCalibration == Calibration::SizeCalibration::NONE) {
600         mSizeScale = 0.0f;
601         return;
602     }
603 
604     // Size of diagonal axis.
605     const float diagonalSize = hypotf(mDisplayBounds.width, mDisplayBounds.height);
606 
607     // Size factors.
608     if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.touchMajor.maxValue != 0) {
609         mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
610     } else if (mRawPointerAxes.toolMajor.valid && mRawPointerAxes.toolMajor.maxValue != 0) {
611         mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
612     } else {
613         mSizeScale = 0.0f;
614     }
615 
616     mOrientedRanges.touchMajor = InputDeviceInfo::MotionRange{
617             .axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR,
618             .source = mSource,
619             .min = 0,
620             .max = diagonalSize,
621             .flat = 0,
622             .fuzz = 0,
623             .resolution = 0,
624     };
625 
626     if (mRawPointerAxes.touchMajor.valid) {
627         mRawPointerAxes.touchMajor.resolution =
628                 clampResolution("touchMajor", mRawPointerAxes.touchMajor.resolution);
629         mOrientedRanges.touchMajor->resolution = mRawPointerAxes.touchMajor.resolution;
630     }
631 
632     mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
633     mOrientedRanges.touchMinor->axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
634     if (mRawPointerAxes.touchMinor.valid) {
635         mRawPointerAxes.touchMinor.resolution =
636                 clampResolution("touchMinor", mRawPointerAxes.touchMinor.resolution);
637         mOrientedRanges.touchMinor->resolution = mRawPointerAxes.touchMinor.resolution;
638     }
639 
640     mOrientedRanges.toolMajor = InputDeviceInfo::MotionRange{
641             .axis = AMOTION_EVENT_AXIS_TOOL_MAJOR,
642             .source = mSource,
643             .min = 0,
644             .max = diagonalSize,
645             .flat = 0,
646             .fuzz = 0,
647             .resolution = 0,
648     };
649     if (mRawPointerAxes.toolMajor.valid) {
650         mRawPointerAxes.toolMajor.resolution =
651                 clampResolution("toolMajor", mRawPointerAxes.toolMajor.resolution);
652         mOrientedRanges.toolMajor->resolution = mRawPointerAxes.toolMajor.resolution;
653     }
654 
655     mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
656     mOrientedRanges.toolMinor->axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
657     if (mRawPointerAxes.toolMinor.valid) {
658         mRawPointerAxes.toolMinor.resolution =
659                 clampResolution("toolMinor", mRawPointerAxes.toolMinor.resolution);
660         mOrientedRanges.toolMinor->resolution = mRawPointerAxes.toolMinor.resolution;
661     }
662 
663     if (mCalibration.sizeCalibration == Calibration::SizeCalibration::GEOMETRIC) {
664         mOrientedRanges.touchMajor->resolution *= mGeometricScale;
665         mOrientedRanges.touchMinor->resolution *= mGeometricScale;
666         mOrientedRanges.toolMajor->resolution *= mGeometricScale;
667         mOrientedRanges.toolMinor->resolution *= mGeometricScale;
668     } else {
669         // Support for other calibrations can be added here.
670         ALOGW("%s calibration is not supported for size ranges at the moment. "
671               "Using raw resolution instead",
672               ftl::enum_string(mCalibration.sizeCalibration).c_str());
673     }
674 
675     mOrientedRanges.size = InputDeviceInfo::MotionRange{
676             .axis = AMOTION_EVENT_AXIS_SIZE,
677             .source = mSource,
678             .min = 0,
679             .max = 1.0,
680             .flat = 0,
681             .fuzz = 0,
682             .resolution = 0,
683     };
684 }
685 
initializeOrientedRanges()686 void TouchInputMapper::initializeOrientedRanges() {
687     // Configure X and Y factors.
688     const float orientedScaleX = mRawToDisplay.getScaleX();
689     const float orientedScaleY = mRawToDisplay.getScaleY();
690     mOrientedXPrecision = 1.0f / orientedScaleX;
691     mOrientedYPrecision = 1.0f / orientedScaleY;
692 
693     mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
694     mOrientedRanges.x.source = mSource;
695     mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
696     mOrientedRanges.y.source = mSource;
697 
698     // Scale factor for terms that are not oriented in a particular axis.
699     // If the pixels are square then xScale == yScale otherwise we fake it
700     // by choosing an average.
701     mGeometricScale = avg(orientedScaleX, orientedScaleY);
702 
703     initializeSizeRanges();
704 
705     // Pressure factors.
706     mPressureScale = 0;
707     float pressureMax = 1.0;
708     if (mCalibration.pressureCalibration == Calibration::PressureCalibration::PHYSICAL ||
709         mCalibration.pressureCalibration == Calibration::PressureCalibration::AMPLITUDE) {
710         if (mCalibration.pressureScale) {
711             mPressureScale = *mCalibration.pressureScale;
712             pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
713         } else if (mRawPointerAxes.pressure.valid && mRawPointerAxes.pressure.maxValue != 0) {
714             mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
715         }
716     }
717 
718     mOrientedRanges.pressure = InputDeviceInfo::MotionRange{
719             .axis = AMOTION_EVENT_AXIS_PRESSURE,
720             .source = mSource,
721             .min = 0,
722             .max = pressureMax,
723             .flat = 0,
724             .fuzz = 0,
725             .resolution = 0,
726     };
727 
728     // Tilt
729     mTiltXCenter = 0;
730     mTiltXScale = 0;
731     mTiltYCenter = 0;
732     mTiltYScale = 0;
733     mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
734     if (mHaveTilt) {
735         mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue, mRawPointerAxes.tiltX.maxValue);
736         mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue, mRawPointerAxes.tiltY.maxValue);
737         mTiltXScale = M_PI / 180;
738         mTiltYScale = M_PI / 180;
739 
740         if (mRawPointerAxes.tiltX.resolution) {
741             mTiltXScale = 1.0 / mRawPointerAxes.tiltX.resolution;
742         }
743         if (mRawPointerAxes.tiltY.resolution) {
744             mTiltYScale = 1.0 / mRawPointerAxes.tiltY.resolution;
745         }
746 
747         mOrientedRanges.tilt = InputDeviceInfo::MotionRange{
748                 .axis = AMOTION_EVENT_AXIS_TILT,
749                 .source = mSource,
750                 .min = 0,
751                 .max = M_PI_2,
752                 .flat = 0,
753                 .fuzz = 0,
754                 .resolution = 0,
755         };
756     }
757 
758     // Orientation
759     mOrientationScale = 0;
760     if (mHaveTilt) {
761         mOrientedRanges.orientation = InputDeviceInfo::MotionRange{
762                 .axis = AMOTION_EVENT_AXIS_ORIENTATION,
763                 .source = mSource,
764                 .min = -M_PI,
765                 .max = M_PI,
766                 .flat = 0,
767                 .fuzz = 0,
768                 .resolution = 0,
769         };
770 
771     } else if (mCalibration.orientationCalibration != Calibration::OrientationCalibration::NONE) {
772         if (mCalibration.orientationCalibration ==
773             Calibration::OrientationCalibration::INTERPOLATED) {
774             if (mRawPointerAxes.orientation.valid) {
775                 if (mRawPointerAxes.orientation.maxValue > 0) {
776                     mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
777                 } else if (mRawPointerAxes.orientation.minValue < 0) {
778                     mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
779                 } else {
780                     mOrientationScale = 0;
781                 }
782             }
783         }
784 
785         mOrientedRanges.orientation = InputDeviceInfo::MotionRange{
786                 .axis = AMOTION_EVENT_AXIS_ORIENTATION,
787                 .source = mSource,
788                 .min = -M_PI_2,
789                 .max = M_PI_2,
790                 .flat = 0,
791                 .fuzz = 0,
792                 .resolution = 0,
793         };
794     }
795 
796     // Distance
797     mDistanceScale = 0;
798     if (mCalibration.distanceCalibration != Calibration::DistanceCalibration::NONE) {
799         if (mCalibration.distanceCalibration == Calibration::DistanceCalibration::SCALED) {
800             mDistanceScale = mCalibration.distanceScale.value_or(1.0f);
801         }
802 
803         mOrientedRanges.distance = InputDeviceInfo::MotionRange{
804 
805                 .axis = AMOTION_EVENT_AXIS_DISTANCE,
806                 .source = mSource,
807                 .min = mRawPointerAxes.distance.minValue * mDistanceScale,
808                 .max = mRawPointerAxes.distance.maxValue * mDistanceScale,
809                 .flat = 0,
810                 .fuzz = mRawPointerAxes.distance.fuzz * mDistanceScale,
811                 .resolution = 0,
812         };
813     }
814 
815     // Oriented X/Y range (in the rotated display's orientation)
816     const FloatRect rawFrame = Rect{mRawPointerAxes.x.minValue, mRawPointerAxes.y.minValue,
817                                     mRawPointerAxes.x.maxValue, mRawPointerAxes.y.maxValue}
818                                        .toFloatRect();
819     const auto orientedRangeRect = mRawToRotatedDisplay.transform(rawFrame);
820     mOrientedRanges.x.min = orientedRangeRect.left;
821     mOrientedRanges.y.min = orientedRangeRect.top;
822     mOrientedRanges.x.max = orientedRangeRect.right;
823     mOrientedRanges.y.max = orientedRangeRect.bottom;
824 
825     // Oriented flat (in the rotated display's orientation)
826     const auto orientedFlat =
827             transformWithoutTranslation(mRawToRotatedDisplay,
828                                         {static_cast<float>(mRawPointerAxes.x.flat),
829                                          static_cast<float>(mRawPointerAxes.y.flat)});
830     mOrientedRanges.x.flat = std::abs(orientedFlat.x);
831     mOrientedRanges.y.flat = std::abs(orientedFlat.y);
832 
833     // Oriented fuzz (in the rotated display's orientation)
834     const auto orientedFuzz =
835             transformWithoutTranslation(mRawToRotatedDisplay,
836                                         {static_cast<float>(mRawPointerAxes.x.fuzz),
837                                          static_cast<float>(mRawPointerAxes.y.fuzz)});
838     mOrientedRanges.x.fuzz = std::abs(orientedFuzz.x);
839     mOrientedRanges.y.fuzz = std::abs(orientedFuzz.y);
840 
841     // Oriented resolution (in the rotated display's orientation)
842     const auto orientedRes =
843             transformWithoutTranslation(mRawToRotatedDisplay,
844                                         {static_cast<float>(mRawPointerAxes.x.resolution),
845                                          static_cast<float>(mRawPointerAxes.y.resolution)});
846     mOrientedRanges.x.resolution = std::abs(orientedRes.x);
847     mOrientedRanges.y.resolution = std::abs(orientedRes.y);
848 }
849 
computeInputTransforms()850 void TouchInputMapper::computeInputTransforms() {
851     constexpr auto isRotated = [](const ui::Transform::RotationFlags& rotation) {
852         return rotation == ui::Transform::ROT_90 || rotation == ui::Transform::ROT_270;
853     };
854 
855     // See notes about input coordinates in the inputflinger docs:
856     // //frameworks/native/services/inputflinger/docs/input_coordinates.md
857 
858     // Step 1: Undo the raw offset so that the raw coordinate space now starts at (0, 0).
859     ui::Transform undoOffsetInRaw;
860     undoOffsetInRaw.set(-mRawPointerAxes.x.minValue, -mRawPointerAxes.y.minValue);
861 
862     // Step 2: Rotate the raw coordinates to account for input device orientation. The coordinates
863     // will now be in the same orientation as the display in ROTATION_0.
864     // Note: Negating an ui::Rotation value will give its inverse rotation.
865     const auto inputDeviceOrientation = ui::Transform::toRotationFlags(-mParameters.orientation);
866     const ui::Size orientedRawSize = isRotated(inputDeviceOrientation)
867             ? ui::Size{mRawPointerAxes.getRawHeight(), mRawPointerAxes.getRawWidth()}
868             : ui::Size{mRawPointerAxes.getRawWidth(), mRawPointerAxes.getRawHeight()};
869     // When rotating raw values, account for the extra unit added when calculating the raw range.
870     const auto orientInRaw = ui::Transform(inputDeviceOrientation, orientedRawSize.width - 1,
871                                            orientedRawSize.height - 1);
872 
873     // Step 3: Rotate the raw coordinates to account for the display rotation. The coordinates will
874     // now be in the same orientation as the rotated display. There is no need to rotate the
875     // coordinates to the display rotation if the device is not orientation-aware.
876     const auto viewportRotation = ui::Transform::toRotationFlags(-mViewport.orientation);
877     const auto rotatedRawSize = mParameters.orientationAware && isRotated(viewportRotation)
878             ? ui::Size{orientedRawSize.height, orientedRawSize.width}
879             : orientedRawSize;
880     // When rotating raw values, account for the extra unit added when calculating the raw range.
881     const auto rotateInRaw = mParameters.orientationAware
882             ? ui::Transform(viewportRotation, rotatedRawSize.width - 1, rotatedRawSize.height - 1)
883             : ui::Transform();
884 
885     // Step 4: Scale the raw coordinates to the display space.
886     // - In DIRECT mode, we assume that the raw surface of the touch device maps perfectly to
887     //   the surface of the display panel. This is usually true for touchscreens.
888     // - In POINTER mode, we cannot assume that the display and the touch device have the same
889     //   aspect ratio, since it is likely to be untrue for devices like external drawing tablets.
890     //   In this case, we used a fixed scale so that 1) we use the same scale across both the x and
891     //   y axes to ensure the mapping does not stretch gestures, and 2) the entire region of the
892     //   display can be reached by the touch device.
893     // - From this point onward, we are no longer in the discrete space of the raw coordinates but
894     //   are in the continuous space of the logical display.
895     ui::Transform scaleRawToDisplay;
896     const float xScale = static_cast<float>(mViewport.deviceWidth) / rotatedRawSize.width;
897     const float yScale = static_cast<float>(mViewport.deviceHeight) / rotatedRawSize.height;
898     if (mDeviceMode == DeviceMode::DIRECT) {
899         scaleRawToDisplay.set(xScale, 0, 0, yScale);
900     } else if (mDeviceMode == DeviceMode::POINTER) {
901         const float fixedScale = std::max(xScale, yScale);
902         scaleRawToDisplay.set(fixedScale, 0, 0, fixedScale);
903     } else {
904         LOG_ALWAYS_FATAL("computeInputTransform can only be used for DIRECT and POINTER modes");
905     }
906 
907     // Step 5: Undo the display rotation to bring us back to the un-rotated display coordinate space
908     // that InputReader uses.
909     const auto undoRotateInDisplay =
910             ui::Transform(viewportRotation, mViewport.deviceWidth, mViewport.deviceHeight)
911                     .inverse();
912 
913     // Now put it all together!
914     mRawToRotatedDisplay = (scaleRawToDisplay * (rotateInRaw * (orientInRaw * undoOffsetInRaw)));
915     mRawToDisplay = (undoRotateInDisplay * mRawToRotatedDisplay);
916     mRawRotation = ui::Transform{mRawToDisplay.getOrientation()};
917 }
918 
configureInputDevice(nsecs_t when,bool * outResetNeeded)919 void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) {
920     const DeviceMode oldDeviceMode = mDeviceMode;
921 
922     resolveExternalStylusPresence();
923 
924     // Determine device mode.
925     if (mParameters.deviceType == Parameters::DeviceType::POINTER &&
926         mConfig.pointerGesturesEnabled && !mConfig.pointerCaptureRequest.enable) {
927         mSource = AINPUT_SOURCE_MOUSE;
928         mDeviceMode = DeviceMode::POINTER;
929         if (hasStylus()) {
930             mSource |= AINPUT_SOURCE_STYLUS;
931         }
932     } else if (isTouchScreen()) {
933         mSource = AINPUT_SOURCE_TOUCHSCREEN;
934         mDeviceMode = DeviceMode::DIRECT;
935         if (hasStylus()) {
936             mSource |= AINPUT_SOURCE_STYLUS;
937         }
938     } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_NAVIGATION) {
939         mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
940         mDeviceMode = DeviceMode::NAVIGATION;
941     } else {
942         mSource = AINPUT_SOURCE_TOUCHPAD;
943         mDeviceMode = DeviceMode::UNSCALED;
944     }
945 
946     const std::optional<DisplayViewport> newViewportOpt = findViewport();
947 
948     // Ensure the device is valid and can be used.
949     if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
950         ALOGW("Touch device '%s' did not report support for X or Y axis!  "
951               "The device will be inoperable.",
952               getDeviceName().c_str());
953         mDeviceMode = DeviceMode::DISABLED;
954     } else if (!newViewportOpt) {
955         ALOGI("Touch device '%s' could not query the properties of its associated "
956               "display.  The device will be inoperable until the display size "
957               "becomes available.",
958               getDeviceName().c_str());
959         mDeviceMode = DeviceMode::DISABLED;
960     } else if (!mParameters.enableForInactiveViewport && !newViewportOpt->isActive) {
961         ALOGI("Disabling %s (device %i) because the associated viewport is not active",
962               getDeviceName().c_str(), getDeviceId());
963         mDeviceMode = DeviceMode::DISABLED;
964     }
965 
966     // Raw width and height in the natural orientation.
967     const ui::Size rawSize{mRawPointerAxes.getRawWidth(), mRawPointerAxes.getRawHeight()};
968     const int32_t rawXResolution = mRawPointerAxes.x.resolution;
969     const int32_t rawYResolution = mRawPointerAxes.y.resolution;
970     // Calculate the mean resolution when both x and y resolution are set, otherwise set it to 0.
971     const float rawMeanResolution =
972             (rawXResolution > 0 && rawYResolution > 0) ? (rawXResolution + rawYResolution) / 2 : 0;
973 
974     const DisplayViewport& newViewport = newViewportOpt.value_or(kUninitializedViewport);
975     const bool viewportChanged = mViewport != newViewport;
976     bool skipViewportUpdate = false;
977     if (viewportChanged) {
978         const bool viewportOrientationChanged = mViewport.orientation != newViewport.orientation;
979         const bool viewportDisplayIdChanged = mViewport.displayId != newViewport.displayId;
980         mViewport = newViewport;
981 
982         if (mDeviceMode == DeviceMode::DIRECT || mDeviceMode == DeviceMode::POINTER) {
983             const auto oldDisplayBounds = mDisplayBounds;
984 
985             mDisplayBounds = getNaturalDisplaySize(mViewport);
986             mPhysicalFrameInRotatedDisplay = {mViewport.physicalLeft, mViewport.physicalTop,
987                                               mViewport.physicalRight, mViewport.physicalBottom};
988 
989             // TODO(b/257118693): Remove the dependence on the old orientation/rotation logic that
990             //     uses mInputDeviceOrientation. The new logic uses the transforms calculated in
991             //     computeInputTransforms().
992             // InputReader works in the un-rotated display coordinate space, so we don't need to do
993             // anything if the device is already orientation-aware. If the device is not
994             // orientation-aware, then we need to apply the inverse rotation of the display so that
995             // when the display rotation is applied later as a part of the per-window transform, we
996             // get the expected screen coordinates.
997             mInputDeviceOrientation = mParameters.orientationAware
998                     ? ui::ROTATION_0
999                     : getInverseRotation(mViewport.orientation);
1000             // For orientation-aware devices that work in the un-rotated coordinate space, the
1001             // viewport update should be skipped if it is only a change in the orientation.
1002             skipViewportUpdate = !viewportDisplayIdChanged && mParameters.orientationAware &&
1003                     mDisplayBounds == oldDisplayBounds && viewportOrientationChanged;
1004 
1005             // Apply the input device orientation for the device.
1006             mInputDeviceOrientation = mInputDeviceOrientation + mParameters.orientation;
1007             computeInputTransforms();
1008         } else {
1009             mDisplayBounds = rawSize;
1010             mPhysicalFrameInRotatedDisplay = Rect{mDisplayBounds};
1011             mInputDeviceOrientation = ui::ROTATION_0;
1012             mRawToDisplay.reset();
1013             mRawToDisplay.set(-mRawPointerAxes.x.minValue, -mRawPointerAxes.y.minValue);
1014             mRawToRotatedDisplay = mRawToDisplay;
1015         }
1016     }
1017 
1018     // If moving between pointer modes, need to reset some state.
1019     bool deviceModeChanged = mDeviceMode != oldDeviceMode;
1020     if (deviceModeChanged) {
1021         mOrientedRanges.clear();
1022     }
1023 
1024     // Create and preserve the pointer controller in the following cases:
1025     const bool isPointerControllerNeeded =
1026             // - when the device is in pointer mode, to show the mouse cursor;
1027             (mDeviceMode == DeviceMode::POINTER) ||
1028             // - when pointer capture is enabled, to preserve the mouse cursor position;
1029             (mParameters.deviceType == Parameters::DeviceType::POINTER &&
1030              mConfig.pointerCaptureRequest.enable) ||
1031             // - when we should be showing touches;
1032             (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches) ||
1033             // - when we should be showing a pointer icon for direct styluses.
1034             (mDeviceMode == DeviceMode::DIRECT && mConfig.stylusPointerIconEnabled && hasStylus());
1035     if (isPointerControllerNeeded) {
1036         if (mPointerController == nullptr) {
1037             mPointerController = getContext()->getPointerController(getDeviceId());
1038         }
1039         if (mConfig.pointerCaptureRequest.enable) {
1040             mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
1041         }
1042     } else {
1043         if (mPointerController != nullptr && mDeviceMode == DeviceMode::DIRECT &&
1044             !mConfig.showTouches) {
1045             mPointerController->clearSpots();
1046         }
1047         mPointerController.reset();
1048     }
1049 
1050     if ((viewportChanged && !skipViewportUpdate) || deviceModeChanged) {
1051         ALOGI("Device reconfigured: id=%d, name='%s', size %s, orientation %d, mode %d, "
1052               "display id %d",
1053               getDeviceId(), getDeviceName().c_str(), toString(mDisplayBounds).c_str(),
1054               mInputDeviceOrientation, mDeviceMode, mViewport.displayId);
1055 
1056         configureVirtualKeys();
1057 
1058         initializeOrientedRanges();
1059 
1060         // Location
1061         updateAffineTransformation();
1062 
1063         if (mDeviceMode == DeviceMode::POINTER) {
1064             // Compute pointer gesture detection parameters.
1065             float rawDiagonal = hypotf(rawSize.width, rawSize.height);
1066             float displayDiagonal = hypotf(mDisplayBounds.width, mDisplayBounds.height);
1067 
1068             // Scale movements such that one whole swipe of the touch pad covers a
1069             // given area relative to the diagonal size of the display when no acceleration
1070             // is applied.
1071             // Assume that the touch pad has a square aspect ratio such that movements in
1072             // X and Y of the same number of raw units cover the same physical distance.
1073             mPointerXMovementScale =
1074                     mConfig.pointerGestureMovementSpeedRatio * displayDiagonal / rawDiagonal;
1075             mPointerYMovementScale = mPointerXMovementScale;
1076 
1077             // Scale zooms to cover a smaller range of the display than movements do.
1078             // This value determines the area around the pointer that is affected by freeform
1079             // pointer gestures.
1080             mPointerXZoomScale =
1081                     mConfig.pointerGestureZoomSpeedRatio * displayDiagonal / rawDiagonal;
1082             mPointerYZoomScale = mPointerXZoomScale;
1083 
1084             // Calculate the min freeform gesture width. It will be 0 when the resolution of any
1085             // axis is non positive value.
1086             const float minFreeformGestureWidth =
1087                     rawMeanResolution * MIN_FREEFORM_GESTURE_WIDTH_IN_MILLIMETER;
1088 
1089             mPointerGestureMaxSwipeWidth =
1090                     std::max(mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal,
1091                              minFreeformGestureWidth);
1092         }
1093 
1094         // Inform the dispatcher about the changes.
1095         *outResetNeeded = true;
1096         bumpGeneration();
1097     }
1098 }
1099 
dumpDisplay(std::string & dump)1100 void TouchInputMapper::dumpDisplay(std::string& dump) {
1101     dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
1102     dump += StringPrintf(INDENT3 "DisplayBounds: %s\n", toString(mDisplayBounds).c_str());
1103     dump += StringPrintf(INDENT3 "PhysicalFrameInRotatedDisplay: %s\n",
1104                          toString(mPhysicalFrameInRotatedDisplay).c_str());
1105     dump += StringPrintf(INDENT3 "InputDeviceOrientation: %d\n", mInputDeviceOrientation);
1106 }
1107 
configureVirtualKeys()1108 void TouchInputMapper::configureVirtualKeys() {
1109     std::vector<VirtualKeyDefinition> virtualKeyDefinitions;
1110     getDeviceContext().getVirtualKeyDefinitions(virtualKeyDefinitions);
1111 
1112     mVirtualKeys.clear();
1113 
1114     if (virtualKeyDefinitions.size() == 0) {
1115         return;
1116     }
1117 
1118     int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
1119     int32_t touchScreenTop = mRawPointerAxes.y.minValue;
1120     int32_t touchScreenWidth = mRawPointerAxes.getRawWidth();
1121     int32_t touchScreenHeight = mRawPointerAxes.getRawHeight();
1122 
1123     for (const VirtualKeyDefinition& virtualKeyDefinition : virtualKeyDefinitions) {
1124         VirtualKey virtualKey;
1125 
1126         virtualKey.scanCode = virtualKeyDefinition.scanCode;
1127         int32_t keyCode;
1128         int32_t dummyKeyMetaState;
1129         uint32_t flags;
1130         if (getDeviceContext().mapKey(virtualKey.scanCode, 0, 0, &keyCode, &dummyKeyMetaState,
1131                                       &flags)) {
1132             ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
1133             continue; // drop the key
1134         }
1135 
1136         virtualKey.keyCode = keyCode;
1137         virtualKey.flags = flags;
1138 
1139         // convert the key definition's display coordinates into touch coordinates for a hit box
1140         int32_t halfWidth = virtualKeyDefinition.width / 2;
1141         int32_t halfHeight = virtualKeyDefinition.height / 2;
1142 
1143         virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth) * touchScreenWidth /
1144                         mDisplayBounds.width +
1145                 touchScreenLeft;
1146         virtualKey.hitRight = (virtualKeyDefinition.centerX + halfWidth) * touchScreenWidth /
1147                         mDisplayBounds.width +
1148                 touchScreenLeft;
1149         virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight) * touchScreenHeight /
1150                         mDisplayBounds.height +
1151                 touchScreenTop;
1152         virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight /
1153                         mDisplayBounds.height +
1154                 touchScreenTop;
1155         mVirtualKeys.push_back(virtualKey);
1156     }
1157 }
1158 
dumpVirtualKeys(std::string & dump)1159 void TouchInputMapper::dumpVirtualKeys(std::string& dump) {
1160     if (!mVirtualKeys.empty()) {
1161         dump += INDENT3 "Virtual Keys:\n";
1162 
1163         for (size_t i = 0; i < mVirtualKeys.size(); i++) {
1164             const VirtualKey& virtualKey = mVirtualKeys[i];
1165             dump += StringPrintf(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
1166                                          "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1167                                  i, virtualKey.scanCode, virtualKey.keyCode, virtualKey.hitLeft,
1168                                  virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1169         }
1170     }
1171 }
1172 
parseCalibration()1173 void TouchInputMapper::parseCalibration() {
1174     const PropertyMap& in = getDeviceContext().getConfiguration();
1175     Calibration& out = mCalibration;
1176 
1177     // Size
1178     out.sizeCalibration = Calibration::SizeCalibration::DEFAULT;
1179     std::optional<std::string> sizeCalibrationString = in.getString("touch.size.calibration");
1180     if (sizeCalibrationString.has_value()) {
1181         if (*sizeCalibrationString == "none") {
1182             out.sizeCalibration = Calibration::SizeCalibration::NONE;
1183         } else if (*sizeCalibrationString == "geometric") {
1184             out.sizeCalibration = Calibration::SizeCalibration::GEOMETRIC;
1185         } else if (*sizeCalibrationString == "diameter") {
1186             out.sizeCalibration = Calibration::SizeCalibration::DIAMETER;
1187         } else if (*sizeCalibrationString == "box") {
1188             out.sizeCalibration = Calibration::SizeCalibration::BOX;
1189         } else if (*sizeCalibrationString == "area") {
1190             out.sizeCalibration = Calibration::SizeCalibration::AREA;
1191         } else if (*sizeCalibrationString != "default") {
1192             ALOGW("Invalid value for touch.size.calibration: '%s'", sizeCalibrationString->c_str());
1193         }
1194     }
1195 
1196     out.sizeScale = in.getFloat("touch.size.scale");
1197     out.sizeBias = in.getFloat("touch.size.bias");
1198     out.sizeIsSummed = in.getBool("touch.size.isSummed");
1199 
1200     // Pressure
1201     out.pressureCalibration = Calibration::PressureCalibration::DEFAULT;
1202     std::optional<std::string> pressureCalibrationString =
1203             in.getString("touch.pressure.calibration");
1204     if (pressureCalibrationString.has_value()) {
1205         if (*pressureCalibrationString == "none") {
1206             out.pressureCalibration = Calibration::PressureCalibration::NONE;
1207         } else if (*pressureCalibrationString == "physical") {
1208             out.pressureCalibration = Calibration::PressureCalibration::PHYSICAL;
1209         } else if (*pressureCalibrationString == "amplitude") {
1210             out.pressureCalibration = Calibration::PressureCalibration::AMPLITUDE;
1211         } else if (*pressureCalibrationString != "default") {
1212             ALOGW("Invalid value for touch.pressure.calibration: '%s'",
1213                   pressureCalibrationString->c_str());
1214         }
1215     }
1216 
1217     out.pressureScale = in.getFloat("touch.pressure.scale");
1218 
1219     // Orientation
1220     out.orientationCalibration = Calibration::OrientationCalibration::DEFAULT;
1221     std::optional<std::string> orientationCalibrationString =
1222             in.getString("touch.orientation.calibration");
1223     if (orientationCalibrationString.has_value()) {
1224         if (*orientationCalibrationString == "none") {
1225             out.orientationCalibration = Calibration::OrientationCalibration::NONE;
1226         } else if (*orientationCalibrationString == "interpolated") {
1227             out.orientationCalibration = Calibration::OrientationCalibration::INTERPOLATED;
1228         } else if (*orientationCalibrationString == "vector") {
1229             out.orientationCalibration = Calibration::OrientationCalibration::VECTOR;
1230         } else if (*orientationCalibrationString != "default") {
1231             ALOGW("Invalid value for touch.orientation.calibration: '%s'",
1232                   orientationCalibrationString->c_str());
1233         }
1234     }
1235 
1236     // Distance
1237     out.distanceCalibration = Calibration::DistanceCalibration::DEFAULT;
1238     std::optional<std::string> distanceCalibrationString =
1239             in.getString("touch.distance.calibration");
1240     if (distanceCalibrationString.has_value()) {
1241         if (*distanceCalibrationString == "none") {
1242             out.distanceCalibration = Calibration::DistanceCalibration::NONE;
1243         } else if (*distanceCalibrationString == "scaled") {
1244             out.distanceCalibration = Calibration::DistanceCalibration::SCALED;
1245         } else if (*distanceCalibrationString != "default") {
1246             ALOGW("Invalid value for touch.distance.calibration: '%s'",
1247                   distanceCalibrationString->c_str());
1248         }
1249     }
1250 
1251     out.distanceScale = in.getFloat("touch.distance.scale");
1252 }
1253 
resolveCalibration()1254 void TouchInputMapper::resolveCalibration() {
1255     // Size
1256     if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
1257         if (mCalibration.sizeCalibration == Calibration::SizeCalibration::DEFAULT) {
1258             mCalibration.sizeCalibration = Calibration::SizeCalibration::GEOMETRIC;
1259         }
1260     } else {
1261         mCalibration.sizeCalibration = Calibration::SizeCalibration::NONE;
1262     }
1263 
1264     // Pressure
1265     if (mRawPointerAxes.pressure.valid) {
1266         if (mCalibration.pressureCalibration == Calibration::PressureCalibration::DEFAULT) {
1267             mCalibration.pressureCalibration = Calibration::PressureCalibration::PHYSICAL;
1268         }
1269     } else {
1270         mCalibration.pressureCalibration = Calibration::PressureCalibration::NONE;
1271     }
1272 
1273     // Orientation
1274     if (mRawPointerAxes.orientation.valid) {
1275         if (mCalibration.orientationCalibration == Calibration::OrientationCalibration::DEFAULT) {
1276             mCalibration.orientationCalibration = Calibration::OrientationCalibration::INTERPOLATED;
1277         }
1278     } else {
1279         mCalibration.orientationCalibration = Calibration::OrientationCalibration::NONE;
1280     }
1281 
1282     // Distance
1283     if (mRawPointerAxes.distance.valid) {
1284         if (mCalibration.distanceCalibration == Calibration::DistanceCalibration::DEFAULT) {
1285             mCalibration.distanceCalibration = Calibration::DistanceCalibration::SCALED;
1286         }
1287     } else {
1288         mCalibration.distanceCalibration = Calibration::DistanceCalibration::NONE;
1289     }
1290 }
1291 
dumpCalibration(std::string & dump)1292 void TouchInputMapper::dumpCalibration(std::string& dump) {
1293     dump += INDENT3 "Calibration:\n";
1294 
1295     dump += INDENT4 "touch.size.calibration: ";
1296     dump += ftl::enum_string(mCalibration.sizeCalibration) + "\n";
1297 
1298     if (mCalibration.sizeScale) {
1299         dump += StringPrintf(INDENT4 "touch.size.scale: %0.3f\n", *mCalibration.sizeScale);
1300     }
1301 
1302     if (mCalibration.sizeBias) {
1303         dump += StringPrintf(INDENT4 "touch.size.bias: %0.3f\n", *mCalibration.sizeBias);
1304     }
1305 
1306     if (mCalibration.sizeIsSummed) {
1307         dump += StringPrintf(INDENT4 "touch.size.isSummed: %s\n",
1308                              toString(*mCalibration.sizeIsSummed));
1309     }
1310 
1311     // Pressure
1312     switch (mCalibration.pressureCalibration) {
1313         case Calibration::PressureCalibration::NONE:
1314             dump += INDENT4 "touch.pressure.calibration: none\n";
1315             break;
1316         case Calibration::PressureCalibration::PHYSICAL:
1317             dump += INDENT4 "touch.pressure.calibration: physical\n";
1318             break;
1319         case Calibration::PressureCalibration::AMPLITUDE:
1320             dump += INDENT4 "touch.pressure.calibration: amplitude\n";
1321             break;
1322         default:
1323             ALOG_ASSERT(false);
1324     }
1325 
1326     if (mCalibration.pressureScale) {
1327         dump += StringPrintf(INDENT4 "touch.pressure.scale: %0.3f\n", *mCalibration.pressureScale);
1328     }
1329 
1330     // Orientation
1331     switch (mCalibration.orientationCalibration) {
1332         case Calibration::OrientationCalibration::NONE:
1333             dump += INDENT4 "touch.orientation.calibration: none\n";
1334             break;
1335         case Calibration::OrientationCalibration::INTERPOLATED:
1336             dump += INDENT4 "touch.orientation.calibration: interpolated\n";
1337             break;
1338         case Calibration::OrientationCalibration::VECTOR:
1339             dump += INDENT4 "touch.orientation.calibration: vector\n";
1340             break;
1341         default:
1342             ALOG_ASSERT(false);
1343     }
1344 
1345     // Distance
1346     switch (mCalibration.distanceCalibration) {
1347         case Calibration::DistanceCalibration::NONE:
1348             dump += INDENT4 "touch.distance.calibration: none\n";
1349             break;
1350         case Calibration::DistanceCalibration::SCALED:
1351             dump += INDENT4 "touch.distance.calibration: scaled\n";
1352             break;
1353         default:
1354             ALOG_ASSERT(false);
1355     }
1356 
1357     if (mCalibration.distanceScale) {
1358         dump += StringPrintf(INDENT4 "touch.distance.scale: %0.3f\n", *mCalibration.distanceScale);
1359     }
1360 }
1361 
dumpAffineTransformation(std::string & dump)1362 void TouchInputMapper::dumpAffineTransformation(std::string& dump) {
1363     dump += INDENT3 "Affine Transformation:\n";
1364 
1365     dump += StringPrintf(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
1366     dump += StringPrintf(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
1367     dump += StringPrintf(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
1368     dump += StringPrintf(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
1369     dump += StringPrintf(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
1370     dump += StringPrintf(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
1371 }
1372 
updateAffineTransformation()1373 void TouchInputMapper::updateAffineTransformation() {
1374     mAffineTransform = getPolicy()->getTouchAffineTransformation(getDeviceContext().getDescriptor(),
1375                                                                  mInputDeviceOrientation);
1376 }
1377 
reset(nsecs_t when)1378 std::list<NotifyArgs> TouchInputMapper::reset(nsecs_t when) {
1379     std::list<NotifyArgs> out = cancelTouch(when, when);
1380     updateTouchSpots();
1381 
1382     mCursorButtonAccumulator.reset(getDeviceContext());
1383     mCursorScrollAccumulator.reset(getDeviceContext());
1384     mTouchButtonAccumulator.reset();
1385 
1386     mPointerVelocityControl.reset();
1387     mWheelXVelocityControl.reset();
1388     mWheelYVelocityControl.reset();
1389 
1390     mRawStatesPending.clear();
1391     mCurrentRawState.clear();
1392     mCurrentCookedState.clear();
1393     mLastRawState.clear();
1394     mLastCookedState.clear();
1395     mPointerUsage = PointerUsage::NONE;
1396     mSentHoverEnter = false;
1397     mHavePointerIds = false;
1398     mCurrentMotionAborted = false;
1399     mDownTime = 0;
1400 
1401     mCurrentVirtualKey.down = false;
1402 
1403     mPointerGesture.reset();
1404     mPointerSimple.reset();
1405     resetExternalStylus();
1406 
1407     if (mPointerController != nullptr) {
1408         mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
1409         mPointerController->clearSpots();
1410     }
1411 
1412     return out += InputMapper::reset(when);
1413 }
1414 
resetExternalStylus()1415 void TouchInputMapper::resetExternalStylus() {
1416     mExternalStylusState.clear();
1417     mFusedStylusPointerId.reset();
1418     mExternalStylusFusionTimeout = LLONG_MAX;
1419     mExternalStylusDataPending = false;
1420     mExternalStylusButtonsApplied = 0;
1421 }
1422 
clearStylusDataPendingFlags()1423 void TouchInputMapper::clearStylusDataPendingFlags() {
1424     mExternalStylusDataPending = false;
1425     mExternalStylusFusionTimeout = LLONG_MAX;
1426 }
1427 
process(const RawEvent * rawEvent)1428 std::list<NotifyArgs> TouchInputMapper::process(const RawEvent* rawEvent) {
1429     mCursorButtonAccumulator.process(rawEvent);
1430     mCursorScrollAccumulator.process(rawEvent);
1431     mTouchButtonAccumulator.process(rawEvent);
1432 
1433     std::list<NotifyArgs> out;
1434     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
1435         out += sync(rawEvent->when, rawEvent->readTime);
1436     }
1437     return out;
1438 }
1439 
sync(nsecs_t when,nsecs_t readTime)1440 std::list<NotifyArgs> TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) {
1441     std::list<NotifyArgs> out;
1442     if (mDeviceMode == DeviceMode::DISABLED) {
1443         // Only save the last pending state when the device is disabled.
1444         mRawStatesPending.clear();
1445     }
1446     // Push a new state.
1447     mRawStatesPending.emplace_back();
1448 
1449     RawState& next = mRawStatesPending.back();
1450     next.clear();
1451     next.when = when;
1452     next.readTime = readTime;
1453 
1454     // Sync button state.
1455     next.buttonState = filterButtonState(mConfig,
1456                                          mTouchButtonAccumulator.getButtonState() |
1457                                                  mCursorButtonAccumulator.getButtonState());
1458 
1459     // Sync scroll
1460     next.rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
1461     next.rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
1462     mCursorScrollAccumulator.finishSync();
1463 
1464     // Sync touch
1465     syncTouch(when, &next);
1466 
1467     // The last RawState is the actually second to last, since we just added a new state
1468     const RawState& last =
1469             mRawStatesPending.size() == 1 ? mCurrentRawState : mRawStatesPending.rbegin()[1];
1470 
1471     std::tie(next.when, next.readTime) =
1472             applyBluetoothTimestampSmoothening(getDeviceContext().getDeviceIdentifier(), when,
1473                                                readTime, last.when);
1474 
1475     // Assign pointer ids.
1476     if (!mHavePointerIds) {
1477         assignPointerIds(last, next);
1478     }
1479 
1480     ALOGD_IF(debugRawEvents(),
1481              "syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
1482              "hovering ids 0x%08x -> 0x%08x, canceled ids 0x%08x",
1483              last.rawPointerData.pointerCount, next.rawPointerData.pointerCount,
1484              last.rawPointerData.touchingIdBits.value, next.rawPointerData.touchingIdBits.value,
1485              last.rawPointerData.hoveringIdBits.value, next.rawPointerData.hoveringIdBits.value,
1486              next.rawPointerData.canceledIdBits.value);
1487 
1488     if (!next.rawPointerData.touchingIdBits.isEmpty() &&
1489         !next.rawPointerData.hoveringIdBits.isEmpty() &&
1490         last.rawPointerData.hoveringIdBits != next.rawPointerData.hoveringIdBits) {
1491         ALOGI("Multi-touch contains some hovering ids 0x%08x",
1492               next.rawPointerData.hoveringIdBits.value);
1493     }
1494 
1495     out += processRawTouches(/*timeout=*/false);
1496     return out;
1497 }
1498 
processRawTouches(bool timeout)1499 std::list<NotifyArgs> TouchInputMapper::processRawTouches(bool timeout) {
1500     std::list<NotifyArgs> out;
1501     if (mDeviceMode == DeviceMode::DISABLED) {
1502         // Do not process raw event while the device is disabled.
1503         return out;
1504     }
1505 
1506     // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
1507     // valid and must go through the full cook and dispatch cycle. This ensures that anything
1508     // touching the current state will only observe the events that have been dispatched to the
1509     // rest of the pipeline.
1510     const size_t N = mRawStatesPending.size();
1511     size_t count;
1512     for (count = 0; count < N; count++) {
1513         const RawState& next = mRawStatesPending[count];
1514 
1515         // A failure to assign the stylus id means that we're waiting on stylus data
1516         // and so should defer the rest of the pipeline.
1517         if (assignExternalStylusId(next, timeout)) {
1518             break;
1519         }
1520 
1521         // All ready to go.
1522         clearStylusDataPendingFlags();
1523         mCurrentRawState = next;
1524         if (mCurrentRawState.when < mLastRawState.when) {
1525             mCurrentRawState.when = mLastRawState.when;
1526             mCurrentRawState.readTime = mLastRawState.readTime;
1527         }
1528         out += cookAndDispatch(mCurrentRawState.when, mCurrentRawState.readTime);
1529     }
1530     if (count != 0) {
1531         mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count);
1532     }
1533 
1534     if (mExternalStylusDataPending) {
1535         if (timeout) {
1536             nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
1537             clearStylusDataPendingFlags();
1538             mCurrentRawState = mLastRawState;
1539             ALOGD_IF(DEBUG_STYLUS_FUSION,
1540                      "Timeout expired, synthesizing event with new stylus data");
1541             const nsecs_t readTime = when; // consider this synthetic event to be zero latency
1542             out += cookAndDispatch(when, readTime);
1543         } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
1544             mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
1545             getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
1546         }
1547     }
1548     return out;
1549 }
1550 
cookAndDispatch(nsecs_t when,nsecs_t readTime)1551 std::list<NotifyArgs> TouchInputMapper::cookAndDispatch(nsecs_t when, nsecs_t readTime) {
1552     std::list<NotifyArgs> out;
1553     // Always start with a clean state.
1554     mCurrentCookedState.clear();
1555 
1556     // Apply stylus buttons to current raw state.
1557     applyExternalStylusButtonState(when);
1558 
1559     // Handle policy on initial down or hover events.
1560     bool initialDown = mLastRawState.rawPointerData.pointerCount == 0 &&
1561             mCurrentRawState.rawPointerData.pointerCount != 0;
1562 
1563     uint32_t policyFlags = 0;
1564     bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
1565     if (initialDown || buttonsPressed) {
1566         // If this is a touch screen, hide the pointer on an initial down.
1567         if (mDeviceMode == DeviceMode::DIRECT) {
1568             getContext()->fadePointer();
1569         }
1570 
1571         if (mParameters.wake) {
1572             policyFlags |= POLICY_FLAG_WAKE;
1573         }
1574     }
1575 
1576     // Consume raw off-screen touches before cooking pointer data.
1577     // If touches are consumed, subsequent code will not receive any pointer data.
1578     bool consumed;
1579     out += consumeRawTouches(when, readTime, policyFlags, consumed /*byref*/);
1580     if (consumed) {
1581         mCurrentRawState.rawPointerData.clear();
1582     }
1583 
1584     // Cook pointer data.  This call populates the mCurrentCookedState.cookedPointerData structure
1585     // with cooked pointer data that has the same ids and indices as the raw data.
1586     // The following code can use either the raw or cooked data, as needed.
1587     cookPointerData();
1588 
1589     // Apply stylus pressure to current cooked state.
1590     applyExternalStylusTouchState(when);
1591 
1592     // Synthesize key down from raw buttons if needed.
1593     out += synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, readTime, getDeviceId(),
1594                                 mSource, mViewport.displayId, policyFlags,
1595                                 mLastCookedState.buttonState, mCurrentCookedState.buttonState);
1596 
1597     // Dispatch the touches either directly or by translation through a pointer on screen.
1598     if (mDeviceMode == DeviceMode::POINTER) {
1599         for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits); !idBits.isEmpty();) {
1600             uint32_t id = idBits.clearFirstMarkedBit();
1601             const RawPointerData::Pointer& pointer =
1602                     mCurrentRawState.rawPointerData.pointerForId(id);
1603             if (isStylusToolType(pointer.toolType)) {
1604                 mCurrentCookedState.stylusIdBits.markBit(id);
1605             } else if (pointer.toolType == ToolType::FINGER ||
1606                        pointer.toolType == ToolType::UNKNOWN) {
1607                 mCurrentCookedState.fingerIdBits.markBit(id);
1608             } else if (pointer.toolType == ToolType::MOUSE) {
1609                 mCurrentCookedState.mouseIdBits.markBit(id);
1610             }
1611         }
1612         for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits); !idBits.isEmpty();) {
1613             uint32_t id = idBits.clearFirstMarkedBit();
1614             const RawPointerData::Pointer& pointer =
1615                     mCurrentRawState.rawPointerData.pointerForId(id);
1616             if (isStylusToolType(pointer.toolType)) {
1617                 mCurrentCookedState.stylusIdBits.markBit(id);
1618             }
1619         }
1620 
1621         // Stylus takes precedence over all tools, then mouse, then finger.
1622         PointerUsage pointerUsage = mPointerUsage;
1623         if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
1624             mCurrentCookedState.mouseIdBits.clear();
1625             mCurrentCookedState.fingerIdBits.clear();
1626             pointerUsage = PointerUsage::STYLUS;
1627         } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
1628             mCurrentCookedState.fingerIdBits.clear();
1629             pointerUsage = PointerUsage::MOUSE;
1630         } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
1631                    isPointerDown(mCurrentRawState.buttonState)) {
1632             pointerUsage = PointerUsage::GESTURES;
1633         }
1634 
1635         out += dispatchPointerUsage(when, readTime, policyFlags, pointerUsage);
1636     } else {
1637         if (!mCurrentMotionAborted) {
1638             updateTouchSpots();
1639             out += dispatchButtonRelease(when, readTime, policyFlags);
1640             out += dispatchHoverExit(when, readTime, policyFlags);
1641             out += dispatchTouches(when, readTime, policyFlags);
1642             out += dispatchHoverEnterAndMove(when, readTime, policyFlags);
1643             out += dispatchButtonPress(when, readTime, policyFlags);
1644         }
1645 
1646         if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
1647             mCurrentMotionAborted = false;
1648         }
1649     }
1650 
1651     // Synthesize key up from raw buttons if needed.
1652     out += synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, readTime, getDeviceId(),
1653                                 mSource, mViewport.displayId, policyFlags,
1654                                 mLastCookedState.buttonState, mCurrentCookedState.buttonState);
1655 
1656     if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
1657         mCurrentStreamModifiedByExternalStylus = false;
1658     }
1659 
1660     // Clear some transient state.
1661     mCurrentRawState.rawVScroll = 0;
1662     mCurrentRawState.rawHScroll = 0;
1663 
1664     // Copy current touch to last touch in preparation for the next cycle.
1665     mLastRawState = mCurrentRawState;
1666     mLastCookedState = mCurrentCookedState;
1667     return out;
1668 }
1669 
updateTouchSpots()1670 void TouchInputMapper::updateTouchSpots() {
1671     if (!mConfig.showTouches || mPointerController == nullptr) {
1672         return;
1673     }
1674 
1675     // Update touch spots when this is a touchscreen even when it's not enabled so that we can
1676     // clear touch spots.
1677     if (mDeviceMode != DeviceMode::DIRECT &&
1678         (mDeviceMode != DeviceMode::DISABLED || !isTouchScreen())) {
1679         return;
1680     }
1681 
1682     mPointerController->setPresentation(PointerControllerInterface::Presentation::SPOT);
1683     mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
1684 
1685     mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords.cbegin(),
1686                                  mCurrentCookedState.cookedPointerData.idToIndex.cbegin(),
1687                                  mCurrentCookedState.cookedPointerData.touchingIdBits |
1688                                          mCurrentCookedState.cookedPointerData.hoveringIdBits,
1689                                  mViewport.displayId);
1690 }
1691 
isTouchScreen()1692 bool TouchInputMapper::isTouchScreen() {
1693     return mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN &&
1694             mParameters.hasAssociatedDisplay;
1695 }
1696 
applyExternalStylusButtonState(nsecs_t when)1697 void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
1698     if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus()) {
1699         // If any of the external buttons are already pressed by the touch device, ignore them.
1700         const int32_t pressedButtons =
1701                 filterButtonState(mConfig,
1702                                   ~mCurrentRawState.buttonState & mExternalStylusState.buttons);
1703         const int32_t releasedButtons =
1704                 mExternalStylusButtonsApplied & ~mExternalStylusState.buttons;
1705 
1706         mCurrentRawState.buttonState |= pressedButtons;
1707         mCurrentRawState.buttonState &= ~releasedButtons;
1708 
1709         mExternalStylusButtonsApplied |= pressedButtons;
1710         mExternalStylusButtonsApplied &= ~releasedButtons;
1711 
1712         if (mExternalStylusButtonsApplied != 0 || releasedButtons != 0) {
1713             mCurrentStreamModifiedByExternalStylus = true;
1714         }
1715     }
1716 }
1717 
applyExternalStylusTouchState(nsecs_t when)1718 void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
1719     CookedPointerData& currentPointerData = mCurrentCookedState.cookedPointerData;
1720     const CookedPointerData& lastPointerData = mLastCookedState.cookedPointerData;
1721     if (!mFusedStylusPointerId || !currentPointerData.isTouching(*mFusedStylusPointerId)) {
1722         return;
1723     }
1724 
1725     mCurrentStreamModifiedByExternalStylus = true;
1726 
1727     float pressure = lastPointerData.isTouching(*mFusedStylusPointerId)
1728             ? lastPointerData.pointerCoordsForId(*mFusedStylusPointerId)
1729                       .getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)
1730             : 0.f;
1731     if (mExternalStylusState.pressure && *mExternalStylusState.pressure > 0.f) {
1732         pressure = *mExternalStylusState.pressure;
1733     }
1734     PointerCoords& coords = currentPointerData.editPointerCoordsWithId(*mFusedStylusPointerId);
1735     coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
1736 
1737     if (mExternalStylusState.toolType != ToolType::UNKNOWN) {
1738         PointerProperties& properties =
1739                 currentPointerData.editPointerPropertiesWithId(*mFusedStylusPointerId);
1740         properties.toolType = mExternalStylusState.toolType;
1741     }
1742 }
1743 
assignExternalStylusId(const RawState & state,bool timeout)1744 bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
1745     if (mDeviceMode != DeviceMode::DIRECT || !hasExternalStylus()) {
1746         return false;
1747     }
1748 
1749     // Check if the stylus pointer has gone up.
1750     if (mFusedStylusPointerId &&
1751         !state.rawPointerData.touchingIdBits.hasBit(*mFusedStylusPointerId)) {
1752         ALOGD_IF(DEBUG_STYLUS_FUSION, "Stylus pointer is going up");
1753         mFusedStylusPointerId.reset();
1754         return false;
1755     }
1756 
1757     const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0 &&
1758             state.rawPointerData.pointerCount != 0;
1759     if (!initialDown) {
1760         return false;
1761     }
1762 
1763     if (!mExternalStylusState.pressure) {
1764         ALOGD_IF(DEBUG_STYLUS_FUSION, "Stylus does not support pressure, no pointer fusion needed");
1765         return false;
1766     }
1767 
1768     if (*mExternalStylusState.pressure != 0.0f) {
1769         ALOGD_IF(DEBUG_STYLUS_FUSION, "Have both stylus and touch data, beginning fusion");
1770         mFusedStylusPointerId = state.rawPointerData.touchingIdBits.firstMarkedBit();
1771         return false;
1772     }
1773 
1774     if (timeout) {
1775         ALOGD_IF(DEBUG_STYLUS_FUSION, "Timeout expired, assuming touch is not a stylus.");
1776         mFusedStylusPointerId.reset();
1777         mExternalStylusFusionTimeout = LLONG_MAX;
1778         return false;
1779     }
1780 
1781     // We are waiting for the external stylus to report a pressure value. Withhold touches from
1782     // being processed until we either get pressure data or timeout.
1783     if (mExternalStylusFusionTimeout == LLONG_MAX) {
1784         mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
1785     }
1786     ALOGD_IF(DEBUG_STYLUS_FUSION,
1787              "No stylus data but stylus is connected, requesting timeout (%" PRId64 "ms)",
1788              mExternalStylusFusionTimeout);
1789     getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
1790     return true;
1791 }
1792 
timeoutExpired(nsecs_t when)1793 std::list<NotifyArgs> TouchInputMapper::timeoutExpired(nsecs_t when) {
1794     std::list<NotifyArgs> out;
1795     if (mDeviceMode == DeviceMode::POINTER) {
1796         if (mPointerUsage == PointerUsage::GESTURES) {
1797             // Since this is a synthetic event, we can consider its latency to be zero
1798             const nsecs_t readTime = when;
1799             out += dispatchPointerGestures(when, readTime, /*policyFlags=*/0, /*isTimeout=*/true);
1800         }
1801     } else if (mDeviceMode == DeviceMode::DIRECT) {
1802         if (mExternalStylusFusionTimeout <= when) {
1803             out += processRawTouches(/*timeout=*/true);
1804         } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
1805             getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
1806         }
1807     }
1808     return out;
1809 }
1810 
updateExternalStylusState(const StylusState & state)1811 std::list<NotifyArgs> TouchInputMapper::updateExternalStylusState(const StylusState& state) {
1812     std::list<NotifyArgs> out;
1813     const bool buttonsChanged = mExternalStylusState.buttons != state.buttons;
1814     mExternalStylusState = state;
1815     if (mFusedStylusPointerId || mExternalStylusFusionTimeout != LLONG_MAX || buttonsChanged) {
1816         // The following three cases are handled here:
1817         // - We're in the middle of a fused stream of data;
1818         // - We're waiting on external stylus data before dispatching the initial down; or
1819         // - Only the button state, which is not reported through a specific pointer, has changed.
1820         // Go ahead and dispatch now that we have fresh stylus data.
1821         mExternalStylusDataPending = true;
1822         out += processRawTouches(/*timeout=*/false);
1823     }
1824     return out;
1825 }
1826 
consumeRawTouches(nsecs_t when,nsecs_t readTime,uint32_t policyFlags,bool & outConsumed)1827 std::list<NotifyArgs> TouchInputMapper::consumeRawTouches(nsecs_t when, nsecs_t readTime,
1828                                                           uint32_t policyFlags, bool& outConsumed) {
1829     outConsumed = false;
1830     std::list<NotifyArgs> out;
1831     // Check for release of a virtual key.
1832     if (mCurrentVirtualKey.down) {
1833         if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
1834             // Pointer went up while virtual key was down.
1835             mCurrentVirtualKey.down = false;
1836             if (!mCurrentVirtualKey.ignored) {
1837                 ALOGD_IF(DEBUG_VIRTUAL_KEYS,
1838                          "VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
1839                          mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1840                 out.push_back(dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_UP,
1841                                                  AKEY_EVENT_FLAG_FROM_SYSTEM |
1842                                                          AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY));
1843             }
1844             outConsumed = true;
1845             return out;
1846         }
1847 
1848         if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
1849             uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
1850             const RawPointerData::Pointer& pointer =
1851                     mCurrentRawState.rawPointerData.pointerForId(id);
1852             const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
1853             if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
1854                 // Pointer is still within the space of the virtual key.
1855                 outConsumed = true;
1856                 return out;
1857             }
1858         }
1859 
1860         // Pointer left virtual key area or another pointer also went down.
1861         // Send key cancellation but do not consume the touch yet.
1862         // This is useful when the user swipes through from the virtual key area
1863         // into the main display surface.
1864         mCurrentVirtualKey.down = false;
1865         if (!mCurrentVirtualKey.ignored) {
1866             ALOGD_IF(DEBUG_VIRTUAL_KEYS, "VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
1867                      mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1868             out.push_back(dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_UP,
1869                                              AKEY_EVENT_FLAG_FROM_SYSTEM |
1870                                                      AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY |
1871                                                      AKEY_EVENT_FLAG_CANCELED));
1872         }
1873     }
1874 
1875     if (!mCurrentRawState.rawPointerData.hoveringIdBits.isEmpty() &&
1876         mCurrentRawState.rawPointerData.touchingIdBits.isEmpty() &&
1877         mDeviceMode != DeviceMode::UNSCALED) {
1878         // We have hovering pointers, and there are no touching pointers.
1879         bool hoveringPointersInFrame = false;
1880         auto hoveringIds = mCurrentRawState.rawPointerData.hoveringIdBits;
1881         while (!hoveringIds.isEmpty()) {
1882             uint32_t id = hoveringIds.clearFirstMarkedBit();
1883             const auto& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
1884             if (isPointInsidePhysicalFrame(pointer.x, pointer.y)) {
1885                 hoveringPointersInFrame = true;
1886                 break;
1887             }
1888         }
1889         if (!hoveringPointersInFrame) {
1890             // All hovering pointers are outside the physical frame.
1891             outConsumed = true;
1892             return out;
1893         }
1894     }
1895 
1896     if (mLastRawState.rawPointerData.touchingIdBits.isEmpty() &&
1897         !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
1898         // Pointer just went down.  Check for virtual key press or off-screen touches.
1899         uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
1900         const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
1901         // Skip checking whether the pointer is inside the physical frame if the device is in
1902         // unscaled or pointer mode.
1903         if (!isPointInsidePhysicalFrame(pointer.x, pointer.y) &&
1904             mDeviceMode != DeviceMode::UNSCALED && mDeviceMode != DeviceMode::POINTER) {
1905             // If exactly one pointer went down, check for virtual key hit.
1906             // Otherwise, we will drop the entire stroke.
1907             if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
1908                 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
1909                 if (virtualKey) {
1910                     mCurrentVirtualKey.down = true;
1911                     mCurrentVirtualKey.downTime = when;
1912                     mCurrentVirtualKey.keyCode = virtualKey->keyCode;
1913                     mCurrentVirtualKey.scanCode = virtualKey->scanCode;
1914                     mCurrentVirtualKey.ignored =
1915                             getContext()->shouldDropVirtualKey(when, virtualKey->keyCode,
1916                                                                virtualKey->scanCode);
1917 
1918                     if (!mCurrentVirtualKey.ignored) {
1919                         ALOGD_IF(DEBUG_VIRTUAL_KEYS,
1920                                  "VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
1921                                  mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1922                         out.push_back(dispatchVirtualKey(when, readTime, policyFlags,
1923                                                          AKEY_EVENT_ACTION_DOWN,
1924                                                          AKEY_EVENT_FLAG_FROM_SYSTEM |
1925                                                                  AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY));
1926                     }
1927                 }
1928             }
1929             outConsumed = true;
1930             return out;
1931         }
1932     }
1933 
1934     // Disable all virtual key touches that happen within a short time interval of the
1935     // most recent touch within the screen area.  The idea is to filter out stray
1936     // virtual key presses when interacting with the touch screen.
1937     //
1938     // Problems we're trying to solve:
1939     //
1940     // 1. While scrolling a list or dragging the window shade, the user swipes down into a
1941     //    virtual key area that is implemented by a separate touch panel and accidentally
1942     //    triggers a virtual key.
1943     //
1944     // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
1945     //    area and accidentally triggers a virtual key.  This often happens when virtual keys
1946     //    are layed out below the screen near to where the on screen keyboard's space bar
1947     //    is displayed.
1948     if (mConfig.virtualKeyQuietTime > 0 &&
1949         !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
1950         getContext()->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
1951     }
1952     return out;
1953 }
1954 
dispatchVirtualKey(nsecs_t when,nsecs_t readTime,uint32_t policyFlags,int32_t keyEventAction,int32_t keyEventFlags)1955 NotifyKeyArgs TouchInputMapper::dispatchVirtualKey(nsecs_t when, nsecs_t readTime,
1956                                                    uint32_t policyFlags, int32_t keyEventAction,
1957                                                    int32_t keyEventFlags) {
1958     int32_t keyCode = mCurrentVirtualKey.keyCode;
1959     int32_t scanCode = mCurrentVirtualKey.scanCode;
1960     nsecs_t downTime = mCurrentVirtualKey.downTime;
1961     int32_t metaState = getContext()->getGlobalMetaState();
1962     policyFlags |= POLICY_FLAG_VIRTUAL;
1963 
1964     return NotifyKeyArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
1965                          AINPUT_SOURCE_KEYBOARD, mViewport.displayId, policyFlags, keyEventAction,
1966                          keyEventFlags, keyCode, scanCode, metaState, downTime);
1967 }
1968 
abortTouches(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)1969 std::list<NotifyArgs> TouchInputMapper::abortTouches(nsecs_t when, nsecs_t readTime,
1970                                                      uint32_t policyFlags) {
1971     std::list<NotifyArgs> out;
1972     if (mCurrentMotionAborted) {
1973         // Current motion event was already aborted.
1974         return out;
1975     }
1976     BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
1977     if (!currentIdBits.isEmpty()) {
1978         int32_t metaState = getContext()->getGlobalMetaState();
1979         int32_t buttonState = mCurrentCookedState.buttonState;
1980         out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
1981                                      AMOTION_EVENT_ACTION_CANCEL, 0, AMOTION_EVENT_FLAG_CANCELED,
1982                                      metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
1983                                      mCurrentCookedState.cookedPointerData.pointerProperties,
1984                                      mCurrentCookedState.cookedPointerData.pointerCoords,
1985                                      mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits,
1986                                      -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime,
1987                                      MotionClassification::NONE));
1988         mCurrentMotionAborted = true;
1989     }
1990     return out;
1991 }
1992 
1993 // Updates pointer coords and properties for pointers with specified ids that have moved.
1994 // Returns true if any of them changed.
updateMovedPointers(const PropertiesArray & inProperties,CoordsArray & inCoords,const IdToIndexArray & inIdToIndex,PropertiesArray & outProperties,CoordsArray & outCoords,IdToIndexArray & outIdToIndex,BitSet32 idBits)1995 static bool updateMovedPointers(const PropertiesArray& inProperties, CoordsArray& inCoords,
1996                                 const IdToIndexArray& inIdToIndex, PropertiesArray& outProperties,
1997                                 CoordsArray& outCoords, IdToIndexArray& outIdToIndex,
1998                                 BitSet32 idBits) {
1999     bool changed = false;
2000     while (!idBits.isEmpty()) {
2001         uint32_t id = idBits.clearFirstMarkedBit();
2002         uint32_t inIndex = inIdToIndex[id];
2003         uint32_t outIndex = outIdToIndex[id];
2004 
2005         const PointerProperties& curInProperties = inProperties[inIndex];
2006         const PointerCoords& curInCoords = inCoords[inIndex];
2007         PointerProperties& curOutProperties = outProperties[outIndex];
2008         PointerCoords& curOutCoords = outCoords[outIndex];
2009 
2010         if (curInProperties != curOutProperties) {
2011             curOutProperties.copyFrom(curInProperties);
2012             changed = true;
2013         }
2014 
2015         if (curInCoords != curOutCoords) {
2016             curOutCoords.copyFrom(curInCoords);
2017             changed = true;
2018         }
2019     }
2020     return changed;
2021 }
2022 
dispatchTouches(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)2023 std::list<NotifyArgs> TouchInputMapper::dispatchTouches(nsecs_t when, nsecs_t readTime,
2024                                                         uint32_t policyFlags) {
2025     std::list<NotifyArgs> out;
2026     BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
2027     BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
2028     int32_t metaState = getContext()->getGlobalMetaState();
2029     int32_t buttonState = mCurrentCookedState.buttonState;
2030 
2031     if (currentIdBits == lastIdBits) {
2032         if (!currentIdBits.isEmpty()) {
2033             // No pointer id changes so this is a move event.
2034             // The listener takes care of batching moves so we don't have to deal with that here.
2035             out.push_back(
2036                     dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE,
2037                                    0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2038                                    mCurrentCookedState.cookedPointerData.pointerProperties,
2039                                    mCurrentCookedState.cookedPointerData.pointerCoords,
2040                                    mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits,
2041                                    -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime,
2042                                    MotionClassification::NONE));
2043         }
2044     } else {
2045         // There may be pointers going up and pointers going down and pointers moving
2046         // all at the same time.
2047         BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
2048         BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
2049         BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2050         BitSet32 dispatchedIdBits(lastIdBits.value);
2051 
2052         // Update last coordinates of pointers that have moved so that we observe the new
2053         // pointer positions at the same time as other pointers that have just gone up.
2054         bool moveNeeded =
2055                 updateMovedPointers(mCurrentCookedState.cookedPointerData.pointerProperties,
2056                                     mCurrentCookedState.cookedPointerData.pointerCoords,
2057                                     mCurrentCookedState.cookedPointerData.idToIndex,
2058                                     mLastCookedState.cookedPointerData.pointerProperties,
2059                                     mLastCookedState.cookedPointerData.pointerCoords,
2060                                     mLastCookedState.cookedPointerData.idToIndex, moveIdBits);
2061         if (buttonState != mLastCookedState.buttonState) {
2062             moveNeeded = true;
2063         }
2064 
2065         // Dispatch pointer up events.
2066         while (!upIdBits.isEmpty()) {
2067             uint32_t upId = upIdBits.clearFirstMarkedBit();
2068             bool isCanceled = mCurrentCookedState.cookedPointerData.canceledIdBits.hasBit(upId);
2069             if (isCanceled) {
2070                 ALOGI("Canceling pointer %d for the palm event was detected.", upId);
2071             }
2072             out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2073                                          AMOTION_EVENT_ACTION_POINTER_UP, 0,
2074                                          isCanceled ? AMOTION_EVENT_FLAG_CANCELED : 0, metaState,
2075                                          buttonState, 0,
2076                                          mLastCookedState.cookedPointerData.pointerProperties,
2077                                          mLastCookedState.cookedPointerData.pointerCoords,
2078                                          mLastCookedState.cookedPointerData.idToIndex,
2079                                          dispatchedIdBits, upId, mOrientedXPrecision,
2080                                          mOrientedYPrecision, mDownTime,
2081                                          MotionClassification::NONE));
2082             dispatchedIdBits.clearBit(upId);
2083             mCurrentCookedState.cookedPointerData.canceledIdBits.clearBit(upId);
2084         }
2085 
2086         // Dispatch move events if any of the remaining pointers moved from their old locations.
2087         // Although applications receive new locations as part of individual pointer up
2088         // events, they do not generally handle them except when presented in a move event.
2089         if (moveNeeded && !moveIdBits.isEmpty()) {
2090             ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
2091             out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2092                                          AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
2093                                          mCurrentCookedState.cookedPointerData.pointerProperties,
2094                                          mCurrentCookedState.cookedPointerData.pointerCoords,
2095                                          mCurrentCookedState.cookedPointerData.idToIndex,
2096                                          dispatchedIdBits, -1, mOrientedXPrecision,
2097                                          mOrientedYPrecision, mDownTime,
2098                                          MotionClassification::NONE));
2099         }
2100 
2101         // Dispatch pointer down events using the new pointer locations.
2102         while (!downIdBits.isEmpty()) {
2103             uint32_t downId = downIdBits.clearFirstMarkedBit();
2104             dispatchedIdBits.markBit(downId);
2105 
2106             if (dispatchedIdBits.count() == 1) {
2107                 // First pointer is going down.  Set down time.
2108                 mDownTime = when;
2109             }
2110 
2111             out.push_back(
2112                     dispatchMotion(when, readTime, policyFlags, mSource,
2113                                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState,
2114                                    0, mCurrentCookedState.cookedPointerData.pointerProperties,
2115                                    mCurrentCookedState.cookedPointerData.pointerCoords,
2116                                    mCurrentCookedState.cookedPointerData.idToIndex,
2117                                    dispatchedIdBits, downId, mOrientedXPrecision,
2118                                    mOrientedYPrecision, mDownTime, MotionClassification::NONE));
2119         }
2120     }
2121     return out;
2122 }
2123 
dispatchHoverExit(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)2124 std::list<NotifyArgs> TouchInputMapper::dispatchHoverExit(nsecs_t when, nsecs_t readTime,
2125                                                           uint32_t policyFlags) {
2126     std::list<NotifyArgs> out;
2127     if (mSentHoverEnter &&
2128         (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty() ||
2129          !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
2130         int32_t metaState = getContext()->getGlobalMetaState();
2131         out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2132                                      AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState,
2133                                      mLastCookedState.buttonState, 0,
2134                                      mLastCookedState.cookedPointerData.pointerProperties,
2135                                      mLastCookedState.cookedPointerData.pointerCoords,
2136                                      mLastCookedState.cookedPointerData.idToIndex,
2137                                      mLastCookedState.cookedPointerData.hoveringIdBits, -1,
2138                                      mOrientedXPrecision, mOrientedYPrecision, mDownTime,
2139                                      MotionClassification::NONE));
2140         mSentHoverEnter = false;
2141     }
2142     return out;
2143 }
2144 
dispatchHoverEnterAndMove(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)2145 std::list<NotifyArgs> TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, nsecs_t readTime,
2146                                                                   uint32_t policyFlags) {
2147     std::list<NotifyArgs> out;
2148     if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty() &&
2149         !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
2150         int32_t metaState = getContext()->getGlobalMetaState();
2151         if (!mSentHoverEnter) {
2152             out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2153                                          AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
2154                                          mCurrentRawState.buttonState, 0,
2155                                          mCurrentCookedState.cookedPointerData.pointerProperties,
2156                                          mCurrentCookedState.cookedPointerData.pointerCoords,
2157                                          mCurrentCookedState.cookedPointerData.idToIndex,
2158                                          mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
2159                                          mOrientedXPrecision, mOrientedYPrecision, mDownTime,
2160                                          MotionClassification::NONE));
2161             mSentHoverEnter = true;
2162         }
2163 
2164         out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2165                                      AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
2166                                      mCurrentRawState.buttonState, 0,
2167                                      mCurrentCookedState.cookedPointerData.pointerProperties,
2168                                      mCurrentCookedState.cookedPointerData.pointerCoords,
2169                                      mCurrentCookedState.cookedPointerData.idToIndex,
2170                                      mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
2171                                      mOrientedXPrecision, mOrientedYPrecision, mDownTime,
2172                                      MotionClassification::NONE));
2173     }
2174     return out;
2175 }
2176 
dispatchButtonRelease(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)2177 std::list<NotifyArgs> TouchInputMapper::dispatchButtonRelease(nsecs_t when, nsecs_t readTime,
2178                                                               uint32_t policyFlags) {
2179     std::list<NotifyArgs> out;
2180     BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
2181     const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData);
2182     const int32_t metaState = getContext()->getGlobalMetaState();
2183     int32_t buttonState = mLastCookedState.buttonState;
2184     while (!releasedButtons.isEmpty()) {
2185         int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
2186         buttonState &= ~actionButton;
2187         out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2188                                      AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
2189                                      metaState, buttonState, 0,
2190                                      mLastCookedState.cookedPointerData.pointerProperties,
2191                                      mLastCookedState.cookedPointerData.pointerCoords,
2192                                      mLastCookedState.cookedPointerData.idToIndex, idBits, -1,
2193                                      mOrientedXPrecision, mOrientedYPrecision, mDownTime,
2194                                      MotionClassification::NONE));
2195     }
2196     return out;
2197 }
2198 
dispatchButtonPress(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)2199 std::list<NotifyArgs> TouchInputMapper::dispatchButtonPress(nsecs_t when, nsecs_t readTime,
2200                                                             uint32_t policyFlags) {
2201     std::list<NotifyArgs> out;
2202     BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
2203     const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData);
2204     const int32_t metaState = getContext()->getGlobalMetaState();
2205     int32_t buttonState = mLastCookedState.buttonState;
2206     while (!pressedButtons.isEmpty()) {
2207         int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
2208         buttonState |= actionButton;
2209         out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2210                                      AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0, metaState,
2211                                      buttonState, 0,
2212                                      mCurrentCookedState.cookedPointerData.pointerProperties,
2213                                      mCurrentCookedState.cookedPointerData.pointerCoords,
2214                                      mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
2215                                      mOrientedXPrecision, mOrientedYPrecision, mDownTime,
2216                                      MotionClassification::NONE));
2217     }
2218     return out;
2219 }
2220 
dispatchGestureButtonRelease(nsecs_t when,uint32_t policyFlags,BitSet32 idBits,nsecs_t readTime)2221 std::list<NotifyArgs> TouchInputMapper::dispatchGestureButtonRelease(nsecs_t when,
2222                                                                      uint32_t policyFlags,
2223                                                                      BitSet32 idBits,
2224                                                                      nsecs_t readTime) {
2225     std::list<NotifyArgs> out;
2226     BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
2227     const int32_t metaState = getContext()->getGlobalMetaState();
2228     int32_t buttonState = mLastCookedState.buttonState;
2229 
2230     while (!releasedButtons.isEmpty()) {
2231         int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
2232         buttonState &= ~actionButton;
2233         out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2234                                      AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
2235                                      metaState, buttonState, 0,
2236                                      mPointerGesture.lastGestureProperties,
2237                                      mPointerGesture.lastGestureCoords,
2238                                      mPointerGesture.lastGestureIdToIndex, idBits, -1,
2239                                      mOrientedXPrecision, mOrientedYPrecision,
2240                                      mPointerGesture.downTime, MotionClassification::NONE));
2241     }
2242     return out;
2243 }
2244 
dispatchGestureButtonPress(nsecs_t when,uint32_t policyFlags,BitSet32 idBits,nsecs_t readTime)2245 std::list<NotifyArgs> TouchInputMapper::dispatchGestureButtonPress(nsecs_t when,
2246                                                                    uint32_t policyFlags,
2247                                                                    BitSet32 idBits,
2248                                                                    nsecs_t readTime) {
2249     std::list<NotifyArgs> out;
2250     BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
2251     const int32_t metaState = getContext()->getGlobalMetaState();
2252     int32_t buttonState = mLastCookedState.buttonState;
2253 
2254     while (!pressedButtons.isEmpty()) {
2255         int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
2256         buttonState |= actionButton;
2257         out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2258                                      AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0, metaState,
2259                                      buttonState, 0, mPointerGesture.currentGestureProperties,
2260                                      mPointerGesture.currentGestureCoords,
2261                                      mPointerGesture.currentGestureIdToIndex, idBits, -1,
2262                                      mOrientedXPrecision, mOrientedYPrecision,
2263                                      mPointerGesture.downTime, MotionClassification::NONE));
2264     }
2265     return out;
2266 }
2267 
findActiveIdBits(const CookedPointerData & cookedPointerData)2268 const BitSet32& TouchInputMapper::findActiveIdBits(const CookedPointerData& cookedPointerData) {
2269     if (!cookedPointerData.touchingIdBits.isEmpty()) {
2270         return cookedPointerData.touchingIdBits;
2271     }
2272     return cookedPointerData.hoveringIdBits;
2273 }
2274 
cookPointerData()2275 void TouchInputMapper::cookPointerData() {
2276     uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
2277 
2278     mCurrentCookedState.cookedPointerData.clear();
2279     mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
2280     mCurrentCookedState.cookedPointerData.hoveringIdBits =
2281             mCurrentRawState.rawPointerData.hoveringIdBits;
2282     mCurrentCookedState.cookedPointerData.touchingIdBits =
2283             mCurrentRawState.rawPointerData.touchingIdBits;
2284     mCurrentCookedState.cookedPointerData.canceledIdBits =
2285             mCurrentRawState.rawPointerData.canceledIdBits;
2286 
2287     if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
2288         mCurrentCookedState.buttonState = 0;
2289     } else {
2290         mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
2291     }
2292 
2293     // Walk through the the active pointers and map device coordinates onto
2294     // display coordinates and adjust for display orientation.
2295     for (uint32_t i = 0; i < currentPointerCount; i++) {
2296         const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
2297 
2298         // Size
2299         float touchMajor, touchMinor, toolMajor, toolMinor, size;
2300         switch (mCalibration.sizeCalibration) {
2301             case Calibration::SizeCalibration::GEOMETRIC:
2302             case Calibration::SizeCalibration::DIAMETER:
2303             case Calibration::SizeCalibration::BOX:
2304             case Calibration::SizeCalibration::AREA:
2305                 if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
2306                     touchMajor = in.touchMajor;
2307                     touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
2308                     toolMajor = in.toolMajor;
2309                     toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
2310                     size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
2311                                                             : in.touchMajor;
2312                 } else if (mRawPointerAxes.touchMajor.valid) {
2313                     toolMajor = touchMajor = in.touchMajor;
2314                     toolMinor = touchMinor =
2315                             mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
2316                     size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
2317                                                             : in.touchMajor;
2318                 } else if (mRawPointerAxes.toolMajor.valid) {
2319                     touchMajor = toolMajor = in.toolMajor;
2320                     touchMinor = toolMinor =
2321                             mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
2322                     size = mRawPointerAxes.toolMinor.valid ? avg(in.toolMajor, in.toolMinor)
2323                                                            : in.toolMajor;
2324                 } else {
2325                     ALOG_ASSERT(false,
2326                                 "No touch or tool axes.  "
2327                                 "Size calibration should have been resolved to NONE.");
2328                     touchMajor = 0;
2329                     touchMinor = 0;
2330                     toolMajor = 0;
2331                     toolMinor = 0;
2332                     size = 0;
2333                 }
2334 
2335                 if (mCalibration.sizeIsSummed && *mCalibration.sizeIsSummed) {
2336                     uint32_t touchingCount = mCurrentRawState.rawPointerData.touchingIdBits.count();
2337                     if (touchingCount > 1) {
2338                         touchMajor /= touchingCount;
2339                         touchMinor /= touchingCount;
2340                         toolMajor /= touchingCount;
2341                         toolMinor /= touchingCount;
2342                         size /= touchingCount;
2343                     }
2344                 }
2345 
2346                 if (mCalibration.sizeCalibration == Calibration::SizeCalibration::GEOMETRIC) {
2347                     touchMajor *= mGeometricScale;
2348                     touchMinor *= mGeometricScale;
2349                     toolMajor *= mGeometricScale;
2350                     toolMinor *= mGeometricScale;
2351                 } else if (mCalibration.sizeCalibration == Calibration::SizeCalibration::AREA) {
2352                     touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
2353                     touchMinor = touchMajor;
2354                     toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
2355                     toolMinor = toolMajor;
2356                 } else if (mCalibration.sizeCalibration == Calibration::SizeCalibration::DIAMETER) {
2357                     touchMinor = touchMajor;
2358                     toolMinor = toolMajor;
2359                 }
2360 
2361                 mCalibration.applySizeScaleAndBias(touchMajor);
2362                 mCalibration.applySizeScaleAndBias(touchMinor);
2363                 mCalibration.applySizeScaleAndBias(toolMajor);
2364                 mCalibration.applySizeScaleAndBias(toolMinor);
2365                 size *= mSizeScale;
2366                 break;
2367             case Calibration::SizeCalibration::DEFAULT:
2368                 LOG_ALWAYS_FATAL("Resolution should not be 'DEFAULT' at this point");
2369                 break;
2370             case Calibration::SizeCalibration::NONE:
2371                 touchMajor = 0;
2372                 touchMinor = 0;
2373                 toolMajor = 0;
2374                 toolMinor = 0;
2375                 size = 0;
2376                 break;
2377         }
2378 
2379         // Pressure
2380         float pressure;
2381         switch (mCalibration.pressureCalibration) {
2382             case Calibration::PressureCalibration::PHYSICAL:
2383             case Calibration::PressureCalibration::AMPLITUDE:
2384                 pressure = in.pressure * mPressureScale;
2385                 break;
2386             default:
2387                 pressure = in.isHovering ? 0 : 1;
2388                 break;
2389         }
2390 
2391         // Tilt and Orientation
2392         float tilt;
2393         float orientation;
2394         if (mHaveTilt) {
2395             float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
2396             float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
2397             orientation = transformAngle(mRawRotation, atan2f(-sinf(tiltXAngle), sinf(tiltYAngle)));
2398             tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
2399         } else {
2400             tilt = 0;
2401 
2402             switch (mCalibration.orientationCalibration) {
2403                 case Calibration::OrientationCalibration::INTERPOLATED:
2404                     orientation = transformAngle(mRawRotation, in.orientation * mOrientationScale);
2405                     break;
2406                 case Calibration::OrientationCalibration::VECTOR: {
2407                     int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2408                     int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2409                     if (c1 != 0 || c2 != 0) {
2410                         orientation = transformAngle(mRawRotation, atan2f(c1, c2) * 0.5f);
2411                         float confidence = hypotf(c1, c2);
2412                         float scale = 1.0f + confidence / 16.0f;
2413                         touchMajor *= scale;
2414                         touchMinor /= scale;
2415                         toolMajor *= scale;
2416                         toolMinor /= scale;
2417                     } else {
2418                         orientation = 0;
2419                     }
2420                     break;
2421                 }
2422                 default:
2423                     orientation = 0;
2424             }
2425         }
2426 
2427         // Distance
2428         float distance;
2429         switch (mCalibration.distanceCalibration) {
2430             case Calibration::DistanceCalibration::SCALED:
2431                 distance = in.distance * mDistanceScale;
2432                 break;
2433             default:
2434                 distance = 0;
2435         }
2436 
2437         // Adjust X,Y coords for device calibration and convert to the natural display coordinates.
2438         vec2 transformed = {in.x, in.y};
2439         mAffineTransform.applyTo(transformed.x /*byRef*/, transformed.y /*byRef*/);
2440         transformed = mRawToDisplay.transform(transformed);
2441 
2442         // Write output coords.
2443         PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
2444         out.clear();
2445         out.setAxisValue(AMOTION_EVENT_AXIS_X, transformed.x);
2446         out.setAxisValue(AMOTION_EVENT_AXIS_Y, transformed.y);
2447         out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2448         out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2449         out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2450         out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2451         out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
2452         out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
2453         out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
2454         out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
2455         out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
2456 
2457         // Write output relative fields if applicable.
2458         uint32_t id = in.id;
2459         if (mSource == AINPUT_SOURCE_TOUCHPAD &&
2460             mLastCookedState.cookedPointerData.hasPointerCoordsForId(id)) {
2461             const PointerCoords& p = mLastCookedState.cookedPointerData.pointerCoordsForId(id);
2462             float dx = transformed.x - p.getAxisValue(AMOTION_EVENT_AXIS_X);
2463             float dy = transformed.y - p.getAxisValue(AMOTION_EVENT_AXIS_Y);
2464             out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, dx);
2465             out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, dy);
2466         }
2467 
2468         // Write output properties.
2469         PointerProperties& properties = mCurrentCookedState.cookedPointerData.pointerProperties[i];
2470         properties.clear();
2471         properties.id = id;
2472         properties.toolType = in.toolType;
2473 
2474         // Write id index and mark id as valid.
2475         mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
2476         mCurrentCookedState.cookedPointerData.validIdBits.markBit(id);
2477     }
2478 }
2479 
dispatchPointerUsage(nsecs_t when,nsecs_t readTime,uint32_t policyFlags,PointerUsage pointerUsage)2480 std::list<NotifyArgs> TouchInputMapper::dispatchPointerUsage(nsecs_t when, nsecs_t readTime,
2481                                                              uint32_t policyFlags,
2482                                                              PointerUsage pointerUsage) {
2483     std::list<NotifyArgs> out;
2484     if (pointerUsage != mPointerUsage) {
2485         out += abortPointerUsage(when, readTime, policyFlags);
2486         mPointerUsage = pointerUsage;
2487     }
2488 
2489     switch (mPointerUsage) {
2490         case PointerUsage::GESTURES:
2491             out += dispatchPointerGestures(when, readTime, policyFlags, /*isTimeout=*/false);
2492             break;
2493         case PointerUsage::STYLUS:
2494             out += dispatchPointerStylus(when, readTime, policyFlags);
2495             break;
2496         case PointerUsage::MOUSE:
2497             out += dispatchPointerMouse(when, readTime, policyFlags);
2498             break;
2499         case PointerUsage::NONE:
2500             break;
2501     }
2502     return out;
2503 }
2504 
abortPointerUsage(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)2505 std::list<NotifyArgs> TouchInputMapper::abortPointerUsage(nsecs_t when, nsecs_t readTime,
2506                                                           uint32_t policyFlags) {
2507     std::list<NotifyArgs> out;
2508     switch (mPointerUsage) {
2509         case PointerUsage::GESTURES:
2510             out += abortPointerGestures(when, readTime, policyFlags);
2511             break;
2512         case PointerUsage::STYLUS:
2513             out += abortPointerStylus(when, readTime, policyFlags);
2514             break;
2515         case PointerUsage::MOUSE:
2516             out += abortPointerMouse(when, readTime, policyFlags);
2517             break;
2518         case PointerUsage::NONE:
2519             break;
2520     }
2521 
2522     mPointerUsage = PointerUsage::NONE;
2523     return out;
2524 }
2525 
dispatchPointerGestures(nsecs_t when,nsecs_t readTime,uint32_t policyFlags,bool isTimeout)2526 std::list<NotifyArgs> TouchInputMapper::dispatchPointerGestures(nsecs_t when, nsecs_t readTime,
2527                                                                 uint32_t policyFlags,
2528                                                                 bool isTimeout) {
2529     std::list<NotifyArgs> out;
2530     // Update current gesture coordinates.
2531     bool cancelPreviousGesture, finishPreviousGesture;
2532     bool sendEvents =
2533             preparePointerGestures(when, &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
2534     if (!sendEvents) {
2535         return {};
2536     }
2537     if (finishPreviousGesture) {
2538         cancelPreviousGesture = false;
2539     }
2540 
2541     // Update the pointer presentation and spots.
2542     if (mParameters.gestureMode == Parameters::GestureMode::MULTI_TOUCH) {
2543         mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
2544         if (finishPreviousGesture || cancelPreviousGesture) {
2545             mPointerController->clearSpots();
2546         }
2547 
2548         if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) {
2549             mPointerController->setSpots(mPointerGesture.currentGestureCoords.cbegin(),
2550                                          mPointerGesture.currentGestureIdToIndex.cbegin(),
2551                                          mPointerGesture.currentGestureIdBits,
2552                                          mPointerController->getDisplayId());
2553         }
2554     } else {
2555         mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
2556     }
2557 
2558     // Show or hide the pointer if needed.
2559     switch (mPointerGesture.currentGestureMode) {
2560         case PointerGesture::Mode::NEUTRAL:
2561         case PointerGesture::Mode::QUIET:
2562             if (mParameters.gestureMode == Parameters::GestureMode::MULTI_TOUCH &&
2563                 mPointerGesture.lastGestureMode == PointerGesture::Mode::FREEFORM) {
2564                 // Remind the user of where the pointer is after finishing a gesture with spots.
2565                 mPointerController->unfade(PointerControllerInterface::Transition::GRADUAL);
2566             }
2567             break;
2568         case PointerGesture::Mode::TAP:
2569         case PointerGesture::Mode::TAP_DRAG:
2570         case PointerGesture::Mode::BUTTON_CLICK_OR_DRAG:
2571         case PointerGesture::Mode::HOVER:
2572         case PointerGesture::Mode::PRESS:
2573         case PointerGesture::Mode::SWIPE:
2574             // Unfade the pointer when the current gesture manipulates the
2575             // area directly under the pointer.
2576             mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
2577             break;
2578         case PointerGesture::Mode::FREEFORM:
2579             // Fade the pointer when the current gesture manipulates a different
2580             // area and there are spots to guide the user experience.
2581             if (mParameters.gestureMode == Parameters::GestureMode::MULTI_TOUCH) {
2582                 mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
2583             } else {
2584                 mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
2585             }
2586             break;
2587     }
2588 
2589     // Send events!
2590     int32_t metaState = getContext()->getGlobalMetaState();
2591     int32_t buttonState = mCurrentCookedState.buttonState;
2592     const MotionClassification classification =
2593             mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE
2594             ? MotionClassification::TWO_FINGER_SWIPE
2595             : MotionClassification::NONE;
2596 
2597     uint32_t flags = 0;
2598 
2599     if (!PointerGesture::canGestureAffectWindowFocus(mPointerGesture.currentGestureMode)) {
2600         flags |= AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE;
2601     }
2602 
2603     // Update last coordinates of pointers that have moved so that we observe the new
2604     // pointer positions at the same time as other pointers that have just gone up.
2605     bool down = mPointerGesture.currentGestureMode == PointerGesture::Mode::TAP ||
2606             mPointerGesture.currentGestureMode == PointerGesture::Mode::TAP_DRAG ||
2607             mPointerGesture.currentGestureMode == PointerGesture::Mode::BUTTON_CLICK_OR_DRAG ||
2608             mPointerGesture.currentGestureMode == PointerGesture::Mode::PRESS ||
2609             mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE ||
2610             mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM;
2611     bool moveNeeded = false;
2612     if (down && !cancelPreviousGesture && !finishPreviousGesture &&
2613         !mPointerGesture.lastGestureIdBits.isEmpty() &&
2614         !mPointerGesture.currentGestureIdBits.isEmpty()) {
2615         BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value &
2616                                     mPointerGesture.lastGestureIdBits.value);
2617         moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
2618                                          mPointerGesture.currentGestureCoords,
2619                                          mPointerGesture.currentGestureIdToIndex,
2620                                          mPointerGesture.lastGestureProperties,
2621                                          mPointerGesture.lastGestureCoords,
2622                                          mPointerGesture.lastGestureIdToIndex, movedGestureIdBits);
2623         if (buttonState != mLastCookedState.buttonState) {
2624             moveNeeded = true;
2625         }
2626     }
2627 
2628     // Send motion events for all pointers that went up or were canceled.
2629     BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
2630     if (!dispatchedGestureIdBits.isEmpty()) {
2631         if (cancelPreviousGesture) {
2632             const uint32_t cancelFlags = flags | AMOTION_EVENT_FLAG_CANCELED;
2633             out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2634                                          AMOTION_EVENT_ACTION_CANCEL, 0, cancelFlags, metaState,
2635                                          buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2636                                          mPointerGesture.lastGestureProperties,
2637                                          mPointerGesture.lastGestureCoords,
2638                                          mPointerGesture.lastGestureIdToIndex,
2639                                          dispatchedGestureIdBits, -1, 0, 0,
2640                                          mPointerGesture.downTime, classification));
2641 
2642             dispatchedGestureIdBits.clear();
2643         } else {
2644             BitSet32 upGestureIdBits;
2645             if (finishPreviousGesture) {
2646                 upGestureIdBits = dispatchedGestureIdBits;
2647             } else {
2648                 upGestureIdBits.value =
2649                         dispatchedGestureIdBits.value & ~mPointerGesture.currentGestureIdBits.value;
2650             }
2651             while (!upGestureIdBits.isEmpty()) {
2652                 if (((mLastCookedState.buttonState & AMOTION_EVENT_BUTTON_PRIMARY) != 0 ||
2653                      (mLastCookedState.buttonState & AMOTION_EVENT_BUTTON_SECONDARY) != 0) &&
2654                     mPointerGesture.lastGestureMode == PointerGesture::Mode::BUTTON_CLICK_OR_DRAG) {
2655                     out += dispatchGestureButtonRelease(when, policyFlags, dispatchedGestureIdBits,
2656                                                         readTime);
2657                 }
2658                 const uint32_t id = upGestureIdBits.clearFirstMarkedBit();
2659                 out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2660                                              AMOTION_EVENT_ACTION_POINTER_UP, 0, flags, metaState,
2661                                              buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2662                                              mPointerGesture.lastGestureProperties,
2663                                              mPointerGesture.lastGestureCoords,
2664                                              mPointerGesture.lastGestureIdToIndex,
2665                                              dispatchedGestureIdBits, id, 0, 0,
2666                                              mPointerGesture.downTime, classification));
2667 
2668                 dispatchedGestureIdBits.clearBit(id);
2669             }
2670         }
2671     }
2672 
2673     // Send motion events for all pointers that moved.
2674     if (moveNeeded) {
2675         out.push_back(
2676                 dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0,
2677                                flags, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2678                                mPointerGesture.currentGestureProperties,
2679                                mPointerGesture.currentGestureCoords,
2680                                mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1,
2681                                0, 0, mPointerGesture.downTime, classification));
2682     }
2683 
2684     // Send motion events for all pointers that went down.
2685     if (down) {
2686         BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value &
2687                                    ~dispatchedGestureIdBits.value);
2688         while (!downGestureIdBits.isEmpty()) {
2689             uint32_t id = downGestureIdBits.clearFirstMarkedBit();
2690             dispatchedGestureIdBits.markBit(id);
2691 
2692             if (dispatchedGestureIdBits.count() == 1) {
2693                 mPointerGesture.downTime = when;
2694             }
2695 
2696             out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2697                                          AMOTION_EVENT_ACTION_POINTER_DOWN, 0, flags, metaState,
2698                                          buttonState, 0, mPointerGesture.currentGestureProperties,
2699                                          mPointerGesture.currentGestureCoords,
2700                                          mPointerGesture.currentGestureIdToIndex,
2701                                          dispatchedGestureIdBits, id, 0, 0,
2702                                          mPointerGesture.downTime, classification));
2703             if (((buttonState & AMOTION_EVENT_BUTTON_PRIMARY) != 0 ||
2704                  (buttonState & AMOTION_EVENT_BUTTON_SECONDARY) != 0) &&
2705                 mPointerGesture.currentGestureMode == PointerGesture::Mode::BUTTON_CLICK_OR_DRAG) {
2706                 out += dispatchGestureButtonPress(when, policyFlags, dispatchedGestureIdBits,
2707                                                   readTime);
2708             }
2709         }
2710     }
2711 
2712     // Send motion events for hover.
2713     if (mPointerGesture.currentGestureMode == PointerGesture::Mode::HOVER) {
2714         out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2715                                      AMOTION_EVENT_ACTION_HOVER_MOVE, 0, flags, metaState,
2716                                      buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2717                                      mPointerGesture.currentGestureProperties,
2718                                      mPointerGesture.currentGestureCoords,
2719                                      mPointerGesture.currentGestureIdToIndex,
2720                                      mPointerGesture.currentGestureIdBits, -1, 0, 0,
2721                                      mPointerGesture.downTime, MotionClassification::NONE));
2722     } else if (dispatchedGestureIdBits.isEmpty() && !mPointerGesture.lastGestureIdBits.isEmpty()) {
2723         // Synthesize a hover move event after all pointers go up to indicate that
2724         // the pointer is hovering again even if the user is not currently touching
2725         // the touch pad.  This ensures that a view will receive a fresh hover enter
2726         // event after a tap.
2727         const auto [x, y] = mPointerController->getPosition();
2728 
2729         PointerProperties pointerProperties;
2730         pointerProperties.clear();
2731         pointerProperties.id = 0;
2732         pointerProperties.toolType = ToolType::FINGER;
2733 
2734         PointerCoords pointerCoords;
2735         pointerCoords.clear();
2736         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2737         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2738 
2739         const int32_t displayId = mPointerController->getDisplayId();
2740         out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
2741                                        mSource, displayId, policyFlags,
2742                                        AMOTION_EVENT_ACTION_HOVER_MOVE, 0, flags, metaState,
2743                                        buttonState, MotionClassification::NONE,
2744                                        AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
2745                                        &pointerCoords, 0, 0, x, y, mPointerGesture.downTime,
2746                                        /* videoFrames */ {}));
2747     }
2748 
2749     // Update state.
2750     mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
2751     if (!down) {
2752         mPointerGesture.lastGestureIdBits.clear();
2753     } else {
2754         mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
2755         for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty();) {
2756             uint32_t id = idBits.clearFirstMarkedBit();
2757             uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
2758             mPointerGesture.lastGestureProperties[index].copyFrom(
2759                     mPointerGesture.currentGestureProperties[index]);
2760             mPointerGesture.lastGestureCoords[index].copyFrom(
2761                     mPointerGesture.currentGestureCoords[index]);
2762             mPointerGesture.lastGestureIdToIndex[id] = index;
2763         }
2764     }
2765     return out;
2766 }
2767 
abortPointerGestures(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)2768 std::list<NotifyArgs> TouchInputMapper::abortPointerGestures(nsecs_t when, nsecs_t readTime,
2769                                                              uint32_t policyFlags) {
2770     const MotionClassification classification =
2771             mPointerGesture.lastGestureMode == PointerGesture::Mode::SWIPE
2772             ? MotionClassification::TWO_FINGER_SWIPE
2773             : MotionClassification::NONE;
2774     std::list<NotifyArgs> out;
2775     // Cancel previously dispatches pointers.
2776     if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
2777         int32_t metaState = getContext()->getGlobalMetaState();
2778         int32_t buttonState = mCurrentRawState.buttonState;
2779         out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
2780                                      AMOTION_EVENT_ACTION_CANCEL, 0, AMOTION_EVENT_FLAG_CANCELED,
2781                                      metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2782                                      mPointerGesture.lastGestureProperties,
2783                                      mPointerGesture.lastGestureCoords,
2784                                      mPointerGesture.lastGestureIdToIndex,
2785                                      mPointerGesture.lastGestureIdBits, -1, 0, 0,
2786                                      mPointerGesture.downTime, classification));
2787     }
2788 
2789     // Reset the current pointer gesture.
2790     mPointerGesture.reset();
2791     mPointerVelocityControl.reset();
2792 
2793     // Remove any current spots.
2794     if (mPointerController != nullptr) {
2795         mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
2796         mPointerController->clearSpots();
2797     }
2798     return out;
2799 }
2800 
preparePointerGestures(nsecs_t when,bool * outCancelPreviousGesture,bool * outFinishPreviousGesture,bool isTimeout)2801 bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture,
2802                                               bool* outFinishPreviousGesture, bool isTimeout) {
2803     *outCancelPreviousGesture = false;
2804     *outFinishPreviousGesture = false;
2805 
2806     // Handle TAP timeout.
2807     if (isTimeout) {
2808         ALOGD_IF(DEBUG_GESTURES, "Gestures: Processing timeout");
2809 
2810         if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP) {
2811             if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
2812                 // The tap/drag timeout has not yet expired.
2813                 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime +
2814                                                    mConfig.pointerGestureTapDragInterval);
2815             } else {
2816                 // The tap is finished.
2817                 ALOGD_IF(DEBUG_GESTURES, "Gestures: TAP finished");
2818                 *outFinishPreviousGesture = true;
2819 
2820                 mPointerGesture.activeGestureId = -1;
2821                 mPointerGesture.currentGestureMode = PointerGesture::Mode::NEUTRAL;
2822                 mPointerGesture.currentGestureIdBits.clear();
2823 
2824                 mPointerVelocityControl.reset();
2825                 return true;
2826             }
2827         }
2828 
2829         // We did not handle this timeout.
2830         return false;
2831     }
2832 
2833     const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
2834     const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
2835 
2836     // Update the velocity tracker.
2837     {
2838         for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty();) {
2839             uint32_t id = idBits.clearFirstMarkedBit();
2840             const RawPointerData::Pointer& pointer =
2841                     mCurrentRawState.rawPointerData.pointerForId(id);
2842             const float x = pointer.x * mPointerXMovementScale;
2843             const float y = pointer.y * mPointerYMovementScale;
2844             mPointerGesture.velocityTracker.addMovement(when, id, AMOTION_EVENT_AXIS_X, x);
2845             mPointerGesture.velocityTracker.addMovement(when, id, AMOTION_EVENT_AXIS_Y, y);
2846         }
2847     }
2848 
2849     // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
2850     // to NEUTRAL, then we should not generate tap event.
2851     if (mPointerGesture.lastGestureMode != PointerGesture::Mode::HOVER &&
2852         mPointerGesture.lastGestureMode != PointerGesture::Mode::TAP &&
2853         mPointerGesture.lastGestureMode != PointerGesture::Mode::TAP_DRAG) {
2854         mPointerGesture.resetTap();
2855     }
2856 
2857     // Pick a new active touch id if needed.
2858     // Choose an arbitrary pointer that just went down, if there is one.
2859     // Otherwise choose an arbitrary remaining pointer.
2860     // This guarantees we always have an active touch id when there is at least one pointer.
2861     // We keep the same active touch id for as long as possible.
2862     if (mPointerGesture.activeTouchId < 0) {
2863         if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
2864             mPointerGesture.activeTouchId = mCurrentCookedState.fingerIdBits.firstMarkedBit();
2865             mPointerGesture.firstTouchTime = when;
2866         }
2867     } else if (!mCurrentCookedState.fingerIdBits.hasBit(mPointerGesture.activeTouchId)) {
2868         mPointerGesture.activeTouchId = !mCurrentCookedState.fingerIdBits.isEmpty()
2869                 ? mCurrentCookedState.fingerIdBits.firstMarkedBit()
2870                 : -1;
2871     }
2872     const int32_t& activeTouchId = mPointerGesture.activeTouchId;
2873 
2874     // Switch states based on button and pointer state.
2875     if (checkForTouchpadQuietTime(when)) {
2876         // Case 1: Quiet time. (QUIET)
2877         ALOGD_IF(DEBUG_GESTURES, "Gestures: QUIET for next %0.3fms",
2878                  (mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval - when) *
2879                          0.000001f);
2880         if (mPointerGesture.lastGestureMode != PointerGesture::Mode::QUIET) {
2881             *outFinishPreviousGesture = true;
2882         }
2883 
2884         mPointerGesture.activeGestureId = -1;
2885         mPointerGesture.currentGestureMode = PointerGesture::Mode::QUIET;
2886         mPointerGesture.currentGestureIdBits.clear();
2887 
2888         mPointerVelocityControl.reset();
2889     } else if (isPointerDown(mCurrentRawState.buttonState)) {
2890         // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
2891         // The pointer follows the active touch point.
2892         // Emit DOWN, MOVE, UP events at the pointer location.
2893         //
2894         // Only the active touch matters; other fingers are ignored.  This policy helps
2895         // to handle the case where the user places a second finger on the touch pad
2896         // to apply the necessary force to depress an integrated button below the surface.
2897         // We don't want the second finger to be delivered to applications.
2898         //
2899         // For this to work well, we need to make sure to track the pointer that is really
2900         // active.  If the user first puts one finger down to click then adds another
2901         // finger to drag then the active pointer should switch to the finger that is
2902         // being dragged.
2903         ALOGD_IF(DEBUG_GESTURES,
2904                  "Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, currentFingerCount=%d",
2905                  activeTouchId, currentFingerCount);
2906         // Reset state when just starting.
2907         if (mPointerGesture.lastGestureMode != PointerGesture::Mode::BUTTON_CLICK_OR_DRAG) {
2908             *outFinishPreviousGesture = true;
2909             mPointerGesture.activeGestureId = 0;
2910         }
2911 
2912         // Switch pointers if needed.
2913         // Find the fastest pointer and follow it.
2914         if (activeTouchId >= 0 && currentFingerCount > 1) {
2915             const auto [bestId, bestSpeed] = getFastestFinger();
2916             if (bestId >= 0 && bestId != activeTouchId) {
2917                 mPointerGesture.activeTouchId = bestId;
2918                 ALOGD_IF(DEBUG_GESTURES,
2919                          "Gestures: BUTTON_CLICK_OR_DRAG switched pointers, bestId=%d, "
2920                          "bestSpeed=%0.3f",
2921                          bestId, bestSpeed);
2922             }
2923         }
2924 
2925         if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
2926             // When using spots, the click will occur at the position of the anchor
2927             // spot and all other spots will move there.
2928             moveMousePointerFromPointerDelta(when, activeTouchId);
2929         } else {
2930             mPointerVelocityControl.reset();
2931         }
2932 
2933         const auto [x, y] = mPointerController->getPosition();
2934 
2935         mPointerGesture.currentGestureMode = PointerGesture::Mode::BUTTON_CLICK_OR_DRAG;
2936         mPointerGesture.currentGestureIdBits.clear();
2937         mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
2938         mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
2939         mPointerGesture.currentGestureProperties[0].clear();
2940         mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
2941         mPointerGesture.currentGestureProperties[0].toolType = ToolType::FINGER;
2942         mPointerGesture.currentGestureCoords[0].clear();
2943         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
2944         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2945         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
2946     } else if (currentFingerCount == 0) {
2947         // Case 3. No fingers down and button is not pressed. (NEUTRAL)
2948         if (mPointerGesture.lastGestureMode != PointerGesture::Mode::NEUTRAL) {
2949             *outFinishPreviousGesture = true;
2950         }
2951 
2952         // Watch for taps coming out of HOVER or TAP_DRAG mode.
2953         // Checking for taps after TAP_DRAG allows us to detect double-taps.
2954         bool tapped = false;
2955         if ((mPointerGesture.lastGestureMode == PointerGesture::Mode::HOVER ||
2956              mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP_DRAG) &&
2957             lastFingerCount == 1) {
2958             if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
2959                 const auto [x, y] = mPointerController->getPosition();
2960                 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
2961                     fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
2962                     ALOGD_IF(DEBUG_GESTURES, "Gestures: TAP");
2963 
2964                     mPointerGesture.tapUpTime = when;
2965                     getContext()->requestTimeoutAtTime(when +
2966                                                        mConfig.pointerGestureTapDragInterval);
2967 
2968                     mPointerGesture.activeGestureId = 0;
2969                     mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP;
2970                     mPointerGesture.currentGestureIdBits.clear();
2971                     mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
2972                     mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
2973                     mPointerGesture.currentGestureProperties[0].clear();
2974                     mPointerGesture.currentGestureProperties[0].id =
2975                             mPointerGesture.activeGestureId;
2976                     mPointerGesture.currentGestureProperties[0].toolType = ToolType::FINGER;
2977                     mPointerGesture.currentGestureCoords[0].clear();
2978                     mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
2979                                                                          mPointerGesture.tapX);
2980                     mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
2981                                                                          mPointerGesture.tapY);
2982                     mPointerGesture.currentGestureCoords[0]
2983                             .setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
2984 
2985                     tapped = true;
2986                 } else {
2987                     ALOGD_IF(DEBUG_GESTURES, "Gestures: Not a TAP, deltaX=%f, deltaY=%f",
2988                              x - mPointerGesture.tapX, y - mPointerGesture.tapY);
2989                 }
2990             } else {
2991                 if (DEBUG_GESTURES) {
2992                     if (mPointerGesture.tapDownTime != LLONG_MIN) {
2993                         ALOGD("Gestures: Not a TAP, %0.3fms since down",
2994                               (when - mPointerGesture.tapDownTime) * 0.000001f);
2995                     } else {
2996                         ALOGD("Gestures: Not a TAP, incompatible mode transitions");
2997                     }
2998                 }
2999             }
3000         }
3001 
3002         mPointerVelocityControl.reset();
3003 
3004         if (!tapped) {
3005             ALOGD_IF(DEBUG_GESTURES, "Gestures: NEUTRAL");
3006             mPointerGesture.activeGestureId = -1;
3007             mPointerGesture.currentGestureMode = PointerGesture::Mode::NEUTRAL;
3008             mPointerGesture.currentGestureIdBits.clear();
3009         }
3010     } else if (currentFingerCount == 1) {
3011         // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
3012         // The pointer follows the active touch point.
3013         // When in HOVER, emit HOVER_MOVE events at the pointer location.
3014         // When in TAP_DRAG, emit MOVE events at the pointer location.
3015         ALOG_ASSERT(activeTouchId >= 0);
3016 
3017         mPointerGesture.currentGestureMode = PointerGesture::Mode::HOVER;
3018         if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP) {
3019             if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
3020                 const auto [x, y] = mPointerController->getPosition();
3021                 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
3022                     fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
3023                     mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP_DRAG;
3024                 } else {
3025                     ALOGD_IF(DEBUG_GESTURES, "Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
3026                              x - mPointerGesture.tapX, y - mPointerGesture.tapY);
3027                 }
3028             } else {
3029                 ALOGD_IF(DEBUG_GESTURES, "Gestures: Not a TAP_DRAG, %0.3fms time since up",
3030                          (when - mPointerGesture.tapUpTime) * 0.000001f);
3031             }
3032         } else if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP_DRAG) {
3033             mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP_DRAG;
3034         }
3035 
3036         if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
3037             // When using spots, the hover or drag will occur at the position of the anchor spot.
3038             moveMousePointerFromPointerDelta(when, activeTouchId);
3039         } else {
3040             mPointerVelocityControl.reset();
3041         }
3042 
3043         bool down;
3044         if (mPointerGesture.currentGestureMode == PointerGesture::Mode::TAP_DRAG) {
3045             ALOGD_IF(DEBUG_GESTURES, "Gestures: TAP_DRAG");
3046             down = true;
3047         } else {
3048             ALOGD_IF(DEBUG_GESTURES, "Gestures: HOVER");
3049             if (mPointerGesture.lastGestureMode != PointerGesture::Mode::HOVER) {
3050                 *outFinishPreviousGesture = true;
3051             }
3052             mPointerGesture.activeGestureId = 0;
3053             down = false;
3054         }
3055 
3056         const auto [x, y] = mPointerController->getPosition();
3057 
3058         mPointerGesture.currentGestureIdBits.clear();
3059         mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3060         mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3061         mPointerGesture.currentGestureProperties[0].clear();
3062         mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
3063         mPointerGesture.currentGestureProperties[0].toolType = ToolType::FINGER;
3064         mPointerGesture.currentGestureCoords[0].clear();
3065         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
3066         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3067         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
3068                                                              down ? 1.0f : 0.0f);
3069 
3070         if (lastFingerCount == 0 && currentFingerCount != 0) {
3071             mPointerGesture.resetTap();
3072             mPointerGesture.tapDownTime = when;
3073             mPointerGesture.tapX = x;
3074             mPointerGesture.tapY = y;
3075         }
3076     } else {
3077         // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
3078         prepareMultiFingerPointerGestures(when, outCancelPreviousGesture, outFinishPreviousGesture);
3079     }
3080 
3081     if (DEBUG_GESTURES) {
3082         ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
3083               "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
3084               "lastGestureMode=%d, lastGestureIdBits=0x%08x",
3085               toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
3086               mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
3087               mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
3088         for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty();) {
3089             uint32_t id = idBits.clearFirstMarkedBit();
3090             uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
3091             const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
3092             const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
3093             ALOGD("  currentGesture[%d]: index=%d, toolType=%s, "
3094                   "x=%0.3f, y=%0.3f, pressure=%0.3f",
3095                   id, index, ftl::enum_string(properties.toolType).c_str(),
3096                   coords.getAxisValue(AMOTION_EVENT_AXIS_X),
3097                   coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
3098                   coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
3099         }
3100         for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty();) {
3101             uint32_t id = idBits.clearFirstMarkedBit();
3102             uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
3103             const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
3104             const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
3105             ALOGD("  lastGesture[%d]: index=%d, toolType=%s, "
3106                   "x=%0.3f, y=%0.3f, pressure=%0.3f",
3107                   id, index, ftl::enum_string(properties.toolType).c_str(),
3108                   coords.getAxisValue(AMOTION_EVENT_AXIS_X),
3109                   coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
3110                   coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
3111         }
3112     }
3113     return true;
3114 }
3115 
checkForTouchpadQuietTime(nsecs_t when)3116 bool TouchInputMapper::checkForTouchpadQuietTime(nsecs_t when) {
3117     if (mPointerGesture.activeTouchId < 0) {
3118         mPointerGesture.resetQuietTime();
3119         return false;
3120     }
3121 
3122     if (when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval) {
3123         return true;
3124     }
3125 
3126     const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
3127     bool isQuietTime = false;
3128     if ((mPointerGesture.lastGestureMode == PointerGesture::Mode::PRESS ||
3129          mPointerGesture.lastGestureMode == PointerGesture::Mode::SWIPE ||
3130          mPointerGesture.lastGestureMode == PointerGesture::Mode::FREEFORM) &&
3131         currentFingerCount < 2) {
3132         // Enter quiet time when exiting swipe or freeform state.
3133         // This is to prevent accidentally entering the hover state and flinging the
3134         // pointer when finishing a swipe and there is still one pointer left onscreen.
3135         isQuietTime = true;
3136     } else if (mPointerGesture.lastGestureMode == PointerGesture::Mode::BUTTON_CLICK_OR_DRAG &&
3137                currentFingerCount >= 2 && !isPointerDown(mCurrentRawState.buttonState)) {
3138         // Enter quiet time when releasing the button and there are still two or more
3139         // fingers down.  This may indicate that one finger was used to press the button
3140         // but it has not gone up yet.
3141         isQuietTime = true;
3142     }
3143     if (isQuietTime) {
3144         mPointerGesture.quietTime = when;
3145     }
3146     return isQuietTime;
3147 }
3148 
getFastestFinger()3149 std::pair<int32_t, float> TouchInputMapper::getFastestFinger() {
3150     int32_t bestId = -1;
3151     float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
3152     for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty();) {
3153         uint32_t id = idBits.clearFirstMarkedBit();
3154         std::optional<float> vx =
3155                 mPointerGesture.velocityTracker.getVelocity(AMOTION_EVENT_AXIS_X, id);
3156         std::optional<float> vy =
3157                 mPointerGesture.velocityTracker.getVelocity(AMOTION_EVENT_AXIS_Y, id);
3158         if (vx && vy) {
3159             float speed = hypotf(*vx, *vy);
3160             if (speed > bestSpeed) {
3161                 bestId = id;
3162                 bestSpeed = speed;
3163             }
3164         }
3165     }
3166     return std::make_pair(bestId, bestSpeed);
3167 }
3168 
prepareMultiFingerPointerGestures(nsecs_t when,bool * cancelPreviousGesture,bool * finishPreviousGesture)3169 void TouchInputMapper::prepareMultiFingerPointerGestures(nsecs_t when, bool* cancelPreviousGesture,
3170                                                          bool* finishPreviousGesture) {
3171     // We need to provide feedback for each finger that goes down so we cannot wait for the fingers
3172     // to move before deciding what to do.
3173     //
3174     // The ambiguous case is deciding what to do when there are two fingers down but they have not
3175     // moved enough to determine whether they are part of a drag or part of a freeform gesture, or
3176     // just a press or long-press at the pointer location.
3177     //
3178     // When there are two fingers we start with the PRESS hypothesis and we generate a down at the
3179     // pointer location.
3180     //
3181     // When the two fingers move enough or when additional fingers are added, we make a decision to
3182     // transition into SWIPE or FREEFORM mode accordingly.
3183     const int32_t activeTouchId = mPointerGesture.activeTouchId;
3184     ALOG_ASSERT(activeTouchId >= 0);
3185 
3186     const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
3187     const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
3188     bool settled =
3189             when >= mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval;
3190     if (mPointerGesture.lastGestureMode != PointerGesture::Mode::PRESS &&
3191         mPointerGesture.lastGestureMode != PointerGesture::Mode::SWIPE &&
3192         mPointerGesture.lastGestureMode != PointerGesture::Mode::FREEFORM) {
3193         *finishPreviousGesture = true;
3194     } else if (!settled && currentFingerCount > lastFingerCount) {
3195         // Additional pointers have gone down but not yet settled.
3196         // Reset the gesture.
3197         ALOGD_IF(DEBUG_GESTURES,
3198                  "Gestures: Resetting gesture since additional pointers went down for "
3199                  "MULTITOUCH, settle time remaining %0.3fms",
3200                  (mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval -
3201                   when) * 0.000001f);
3202         *cancelPreviousGesture = true;
3203     } else {
3204         // Continue previous gesture.
3205         mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
3206     }
3207 
3208     if (*finishPreviousGesture || *cancelPreviousGesture) {
3209         mPointerGesture.currentGestureMode = PointerGesture::Mode::PRESS;
3210         mPointerGesture.activeGestureId = 0;
3211         mPointerGesture.referenceIdBits.clear();
3212         mPointerVelocityControl.reset();
3213 
3214         // Use the centroid and pointer location as the reference points for the gesture.
3215         ALOGD_IF(DEBUG_GESTURES,
3216                  "Gestures: Using centroid as reference for MULTITOUCH, settle time remaining "
3217                  "%0.3fms",
3218                  (mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval -
3219                   when) * 0.000001f);
3220         mCurrentRawState.rawPointerData
3221                 .getCentroidOfTouchingPointers(&mPointerGesture.referenceTouchX,
3222                                                &mPointerGesture.referenceTouchY);
3223         std::tie(mPointerGesture.referenceGestureX, mPointerGesture.referenceGestureY) =
3224                 mPointerController->getPosition();
3225     }
3226 
3227     // Clear the reference deltas for fingers not yet included in the reference calculation.
3228     for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value &
3229                          ~mPointerGesture.referenceIdBits.value);
3230          !idBits.isEmpty();) {
3231         uint32_t id = idBits.clearFirstMarkedBit();
3232         mPointerGesture.referenceDeltas[id].dx = 0;
3233         mPointerGesture.referenceDeltas[id].dy = 0;
3234     }
3235     mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
3236 
3237     // Add delta for all fingers and calculate a common movement delta.
3238     int32_t commonDeltaRawX = 0, commonDeltaRawY = 0;
3239     BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value &
3240                           mCurrentCookedState.fingerIdBits.value);
3241     for (BitSet32 idBits(commonIdBits); !idBits.isEmpty();) {
3242         bool first = (idBits == commonIdBits);
3243         uint32_t id = idBits.clearFirstMarkedBit();
3244         const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
3245         const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
3246         PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
3247         delta.dx += cpd.x - lpd.x;
3248         delta.dy += cpd.y - lpd.y;
3249 
3250         if (first) {
3251             commonDeltaRawX = delta.dx;
3252             commonDeltaRawY = delta.dy;
3253         } else {
3254             commonDeltaRawX = calculateCommonVector(commonDeltaRawX, delta.dx);
3255             commonDeltaRawY = calculateCommonVector(commonDeltaRawY, delta.dy);
3256         }
3257     }
3258 
3259     // Consider transitions from PRESS to SWIPE or MULTITOUCH.
3260     if (mPointerGesture.currentGestureMode == PointerGesture::Mode::PRESS) {
3261         float dist[MAX_POINTER_ID + 1];
3262         int32_t distOverThreshold = 0;
3263         for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) {
3264             uint32_t id = idBits.clearFirstMarkedBit();
3265             PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
3266             dist[id] = hypotf(delta.dx * mPointerXZoomScale, delta.dy * mPointerYZoomScale);
3267             if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
3268                 distOverThreshold += 1;
3269             }
3270         }
3271 
3272         // Only transition when at least two pointers have moved further than
3273         // the minimum distance threshold.
3274         if (distOverThreshold >= 2) {
3275             if (currentFingerCount > 2) {
3276                 // There are more than two pointers, switch to FREEFORM.
3277                 ALOGD_IF(DEBUG_GESTURES,
3278                          "Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
3279                          currentFingerCount);
3280                 *cancelPreviousGesture = true;
3281                 mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
3282             } else {
3283                 // There are exactly two pointers.
3284                 BitSet32 idBits(mCurrentCookedState.fingerIdBits);
3285                 uint32_t id1 = idBits.clearFirstMarkedBit();
3286                 uint32_t id2 = idBits.firstMarkedBit();
3287                 const RawPointerData::Pointer& p1 =
3288                         mCurrentRawState.rawPointerData.pointerForId(id1);
3289                 const RawPointerData::Pointer& p2 =
3290                         mCurrentRawState.rawPointerData.pointerForId(id2);
3291                 float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
3292                 if (mutualDistance > mPointerGestureMaxSwipeWidth) {
3293                     // There are two pointers but they are too far apart for a SWIPE,
3294                     // switch to FREEFORM.
3295                     ALOGD_IF(DEBUG_GESTURES,
3296                              "Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
3297                              mutualDistance, mPointerGestureMaxSwipeWidth);
3298                     *cancelPreviousGesture = true;
3299                     mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
3300                 } else {
3301                     // There are two pointers.  Wait for both pointers to start moving
3302                     // before deciding whether this is a SWIPE or FREEFORM gesture.
3303                     float dist1 = dist[id1];
3304                     float dist2 = dist[id2];
3305                     if (dist1 >= mConfig.pointerGestureMultitouchMinDistance &&
3306                         dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
3307                         // Calculate the dot product of the displacement vectors.
3308                         // When the vectors are oriented in approximately the same direction,
3309                         // the angle betweeen them is near zero and the cosine of the angle
3310                         // approaches 1.0.  Recall that dot(v1, v2) = cos(angle) * mag(v1) *
3311                         // mag(v2).
3312                         PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
3313                         PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
3314                         float dx1 = delta1.dx * mPointerXZoomScale;
3315                         float dy1 = delta1.dy * mPointerYZoomScale;
3316                         float dx2 = delta2.dx * mPointerXZoomScale;
3317                         float dy2 = delta2.dy * mPointerYZoomScale;
3318                         float dot = dx1 * dx2 + dy1 * dy2;
3319                         float cosine = dot / (dist1 * dist2); // denominator always > 0
3320                         if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
3321                             // Pointers are moving in the same direction.  Switch to SWIPE.
3322                             ALOGD_IF(DEBUG_GESTURES,
3323                                      "Gestures: PRESS transitioned to SWIPE, "
3324                                      "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
3325                                      "cosine %0.3f >= %0.3f",
3326                                      dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
3327                                      mConfig.pointerGestureMultitouchMinDistance, cosine,
3328                                      mConfig.pointerGestureSwipeTransitionAngleCosine);
3329                             mPointerGesture.currentGestureMode = PointerGesture::Mode::SWIPE;
3330                         } else {
3331                             // Pointers are moving in different directions.  Switch to FREEFORM.
3332                             ALOGD_IF(DEBUG_GESTURES,
3333                                      "Gestures: PRESS transitioned to FREEFORM, "
3334                                      "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
3335                                      "cosine %0.3f < %0.3f",
3336                                      dist1, mConfig.pointerGestureMultitouchMinDistance, dist2,
3337                                      mConfig.pointerGestureMultitouchMinDistance, cosine,
3338                                      mConfig.pointerGestureSwipeTransitionAngleCosine);
3339                             *cancelPreviousGesture = true;
3340                             mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
3341                         }
3342                     }
3343                 }
3344             }
3345         }
3346     } else if (mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) {
3347         // Switch from SWIPE to FREEFORM if additional pointers go down.
3348         // Cancel previous gesture.
3349         if (currentFingerCount > 2) {
3350             ALOGD_IF(DEBUG_GESTURES,
3351                      "Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
3352                      currentFingerCount);
3353             *cancelPreviousGesture = true;
3354             mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
3355         }
3356     }
3357 
3358     // Move the reference points based on the overall group motion of the fingers
3359     // except in PRESS mode while waiting for a transition to occur.
3360     if (mPointerGesture.currentGestureMode != PointerGesture::Mode::PRESS &&
3361         (commonDeltaRawX || commonDeltaRawY)) {
3362         for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) {
3363             uint32_t id = idBits.clearFirstMarkedBit();
3364             PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
3365             delta.dx = 0;
3366             delta.dy = 0;
3367         }
3368 
3369         mPointerGesture.referenceTouchX += commonDeltaRawX;
3370         mPointerGesture.referenceTouchY += commonDeltaRawY;
3371 
3372         float commonDeltaX = commonDeltaRawX * mPointerXMovementScale;
3373         float commonDeltaY = commonDeltaRawY * mPointerYMovementScale;
3374 
3375         rotateDelta(mInputDeviceOrientation, &commonDeltaX, &commonDeltaY);
3376         mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
3377 
3378         mPointerGesture.referenceGestureX += commonDeltaX;
3379         mPointerGesture.referenceGestureY += commonDeltaY;
3380     }
3381 
3382     // Report gestures.
3383     if (mPointerGesture.currentGestureMode == PointerGesture::Mode::PRESS ||
3384         mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) {
3385         // PRESS or SWIPE mode.
3386         ALOGD_IF(DEBUG_GESTURES,
3387                  "Gestures: PRESS or SWIPE activeTouchId=%d, activeGestureId=%d, "
3388                  "currentTouchPointerCount=%d",
3389                  activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
3390         ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
3391 
3392         mPointerGesture.currentGestureIdBits.clear();
3393         mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3394         mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3395         mPointerGesture.currentGestureProperties[0].clear();
3396         mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
3397         mPointerGesture.currentGestureProperties[0].toolType = ToolType::FINGER;
3398         mPointerGesture.currentGestureCoords[0].clear();
3399         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
3400                                                              mPointerGesture.referenceGestureX);
3401         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
3402                                                              mPointerGesture.referenceGestureY);
3403         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
3404         if (mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) {
3405             float xOffset = static_cast<float>(commonDeltaRawX) /
3406                     (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue);
3407             float yOffset = static_cast<float>(commonDeltaRawY) /
3408                     (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue);
3409             mPointerGesture.currentGestureCoords[0]
3410                     .setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, xOffset);
3411             mPointerGesture.currentGestureCoords[0]
3412                     .setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, yOffset);
3413         }
3414     } else if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) {
3415         // FREEFORM mode.
3416         ALOGD_IF(DEBUG_GESTURES,
3417                  "Gestures: FREEFORM activeTouchId=%d, activeGestureId=%d, "
3418                  "currentTouchPointerCount=%d",
3419                  activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
3420         ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
3421 
3422         mPointerGesture.currentGestureIdBits.clear();
3423 
3424         BitSet32 mappedTouchIdBits;
3425         BitSet32 usedGestureIdBits;
3426         if (mPointerGesture.lastGestureMode != PointerGesture::Mode::FREEFORM) {
3427             // Initially, assign the active gesture id to the active touch point
3428             // if there is one.  No other touch id bits are mapped yet.
3429             if (!*cancelPreviousGesture) {
3430                 mappedTouchIdBits.markBit(activeTouchId);
3431                 usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
3432                 mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
3433                         mPointerGesture.activeGestureId;
3434             } else {
3435                 mPointerGesture.activeGestureId = -1;
3436             }
3437         } else {
3438             // Otherwise, assume we mapped all touches from the previous frame.
3439             // Reuse all mappings that are still applicable.
3440             mappedTouchIdBits.value =
3441                     mLastCookedState.fingerIdBits.value & mCurrentCookedState.fingerIdBits.value;
3442             usedGestureIdBits = mPointerGesture.lastGestureIdBits;
3443 
3444             // Check whether we need to choose a new active gesture id because the
3445             // current went went up.
3446             for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value &
3447                                         ~mCurrentCookedState.fingerIdBits.value);
3448                  !upTouchIdBits.isEmpty();) {
3449                 uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
3450                 uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
3451                 if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
3452                     mPointerGesture.activeGestureId = -1;
3453                     break;
3454                 }
3455             }
3456         }
3457 
3458         ALOGD_IF(DEBUG_GESTURES,
3459                  "Gestures: FREEFORM follow up mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
3460                  "activeGestureId=%d",
3461                  mappedTouchIdBits.value, usedGestureIdBits.value, mPointerGesture.activeGestureId);
3462 
3463         BitSet32 idBits(mCurrentCookedState.fingerIdBits);
3464         for (uint32_t i = 0; i < currentFingerCount; i++) {
3465             uint32_t touchId = idBits.clearFirstMarkedBit();
3466             uint32_t gestureId;
3467             if (!mappedTouchIdBits.hasBit(touchId)) {
3468                 gestureId = usedGestureIdBits.markFirstUnmarkedBit();
3469                 mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
3470                 ALOGD_IF(DEBUG_GESTURES,
3471                          "Gestures: FREEFORM new mapping for touch id %d -> gesture id %d", touchId,
3472                          gestureId);
3473             } else {
3474                 gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
3475                 ALOGD_IF(DEBUG_GESTURES,
3476                          "Gestures: FREEFORM existing mapping for touch id %d -> gesture id %d",
3477                          touchId, gestureId);
3478             }
3479             mPointerGesture.currentGestureIdBits.markBit(gestureId);
3480             mPointerGesture.currentGestureIdToIndex[gestureId] = i;
3481 
3482             const RawPointerData::Pointer& pointer =
3483                     mCurrentRawState.rawPointerData.pointerForId(touchId);
3484             float deltaX = (pointer.x - mPointerGesture.referenceTouchX) * mPointerXZoomScale;
3485             float deltaY = (pointer.y - mPointerGesture.referenceTouchY) * mPointerYZoomScale;
3486             rotateDelta(mInputDeviceOrientation, &deltaX, &deltaY);
3487 
3488             mPointerGesture.currentGestureProperties[i].clear();
3489             mPointerGesture.currentGestureProperties[i].id = gestureId;
3490             mPointerGesture.currentGestureProperties[i].toolType = ToolType::FINGER;
3491             mPointerGesture.currentGestureCoords[i].clear();
3492             mPointerGesture.currentGestureCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X,
3493                                                                  mPointerGesture.referenceGestureX +
3494                                                                          deltaX);
3495             mPointerGesture.currentGestureCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y,
3496                                                                  mPointerGesture.referenceGestureY +
3497                                                                          deltaY);
3498             mPointerGesture.currentGestureCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
3499         }
3500 
3501         if (mPointerGesture.activeGestureId < 0) {
3502             mPointerGesture.activeGestureId = mPointerGesture.currentGestureIdBits.firstMarkedBit();
3503             ALOGD_IF(DEBUG_GESTURES, "Gestures: FREEFORM new activeGestureId=%d",
3504                      mPointerGesture.activeGestureId);
3505         }
3506     }
3507 }
3508 
moveMousePointerFromPointerDelta(nsecs_t when,uint32_t pointerId)3509 void TouchInputMapper::moveMousePointerFromPointerDelta(nsecs_t when, uint32_t pointerId) {
3510     const RawPointerData::Pointer& currentPointer =
3511             mCurrentRawState.rawPointerData.pointerForId(pointerId);
3512     const RawPointerData::Pointer& lastPointer =
3513             mLastRawState.rawPointerData.pointerForId(pointerId);
3514     float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
3515     float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
3516 
3517     rotateDelta(mInputDeviceOrientation, &deltaX, &deltaY);
3518     mPointerVelocityControl.move(when, &deltaX, &deltaY);
3519 
3520     mPointerController->move(deltaX, deltaY);
3521 }
3522 
dispatchPointerStylus(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)3523 std::list<NotifyArgs> TouchInputMapper::dispatchPointerStylus(nsecs_t when, nsecs_t readTime,
3524                                                               uint32_t policyFlags) {
3525     mPointerSimple.currentCoords.clear();
3526     mPointerSimple.currentProperties.clear();
3527 
3528     bool down, hovering;
3529     if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
3530         uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
3531         uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
3532         hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
3533         down = !hovering;
3534 
3535         float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
3536         float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
3537         // Styluses are configured specifically for one display. We only update the
3538         // PointerController for this stylus if the PointerController is configured for
3539         // the same display as this stylus,
3540         if (getAssociatedDisplayId() == mViewport.displayId) {
3541             mPointerController->setPosition(x, y);
3542             std::tie(x, y) = mPointerController->getPosition();
3543         }
3544 
3545         mPointerSimple.currentCoords.copyFrom(
3546                 mCurrentCookedState.cookedPointerData.pointerCoords[index]);
3547         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3548         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3549         mPointerSimple.currentProperties.id = 0;
3550         mPointerSimple.currentProperties.toolType =
3551                 mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
3552     } else {
3553         down = false;
3554         hovering = false;
3555     }
3556 
3557     return dispatchPointerSimple(when, readTime, policyFlags, down, hovering, mViewport.displayId);
3558 }
3559 
abortPointerStylus(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)3560 std::list<NotifyArgs> TouchInputMapper::abortPointerStylus(nsecs_t when, nsecs_t readTime,
3561                                                            uint32_t policyFlags) {
3562     return abortPointerSimple(when, readTime, policyFlags);
3563 }
3564 
dispatchPointerMouse(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)3565 std::list<NotifyArgs> TouchInputMapper::dispatchPointerMouse(nsecs_t when, nsecs_t readTime,
3566                                                              uint32_t policyFlags) {
3567     mPointerSimple.currentCoords.clear();
3568     mPointerSimple.currentProperties.clear();
3569 
3570     bool down, hovering;
3571     if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
3572         uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
3573         if (mLastCookedState.mouseIdBits.hasBit(id)) {
3574             moveMousePointerFromPointerDelta(when, id);
3575         } else {
3576             mPointerVelocityControl.reset();
3577         }
3578 
3579         down = isPointerDown(mCurrentRawState.buttonState);
3580         hovering = !down;
3581 
3582         const auto [x, y] = mPointerController->getPosition();
3583         const uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
3584         mPointerSimple.currentCoords.copyFrom(
3585                 mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
3586         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3587         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3588         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
3589                                                   hovering ? 0.0f : 1.0f);
3590         mPointerSimple.currentProperties.id = 0;
3591         mPointerSimple.currentProperties.toolType =
3592                 mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
3593     } else {
3594         mPointerVelocityControl.reset();
3595 
3596         down = false;
3597         hovering = false;
3598     }
3599 
3600     const int32_t displayId = mPointerController->getDisplayId();
3601     return dispatchPointerSimple(when, readTime, policyFlags, down, hovering, displayId);
3602 }
3603 
abortPointerMouse(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)3604 std::list<NotifyArgs> TouchInputMapper::abortPointerMouse(nsecs_t when, nsecs_t readTime,
3605                                                           uint32_t policyFlags) {
3606     std::list<NotifyArgs> out = abortPointerSimple(when, readTime, policyFlags);
3607 
3608     mPointerVelocityControl.reset();
3609 
3610     return out;
3611 }
3612 
dispatchPointerSimple(nsecs_t when,nsecs_t readTime,uint32_t policyFlags,bool down,bool hovering,int32_t displayId)3613 std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsecs_t readTime,
3614                                                               uint32_t policyFlags, bool down,
3615                                                               bool hovering, int32_t displayId) {
3616     LOG_ALWAYS_FATAL_IF(mDeviceMode != DeviceMode::POINTER,
3617                         "%s cannot be used when the device is not in POINTER mode.", __func__);
3618     std::list<NotifyArgs> out;
3619     int32_t metaState = getContext()->getGlobalMetaState();
3620     auto cursorPosition = mPointerSimple.currentCoords.getXYValue();
3621 
3622     if (displayId == mPointerController->getDisplayId()) {
3623         std::tie(cursorPosition.x, cursorPosition.y) = mPointerController->getPosition();
3624         if (down || hovering) {
3625             mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
3626             mPointerController->clearSpots();
3627             mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
3628         } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
3629             mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
3630         }
3631     }
3632 
3633     if (mPointerSimple.down && !down) {
3634         mPointerSimple.down = false;
3635 
3636         // Send up.
3637         out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
3638                                        mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0,
3639                                        0, metaState, mLastRawState.buttonState,
3640                                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
3641                                        &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
3642                                        mOrientedXPrecision, mOrientedYPrecision,
3643                                        mPointerSimple.lastCursorX, mPointerSimple.lastCursorY,
3644                                        mPointerSimple.downTime,
3645                                        /* videoFrames */ {}));
3646     }
3647 
3648     if (mPointerSimple.hovering && !hovering) {
3649         mPointerSimple.hovering = false;
3650 
3651         // Send hover exit.
3652         out.push_back(
3653                 NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
3654                                  displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0,
3655                                  metaState, mLastRawState.buttonState, MotionClassification::NONE,
3656                                  AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
3657                                  &mPointerSimple.lastCoords, mOrientedXPrecision,
3658                                  mOrientedYPrecision, mPointerSimple.lastCursorX,
3659                                  mPointerSimple.lastCursorY, mPointerSimple.downTime,
3660                                  /* videoFrames */ {}));
3661     }
3662 
3663     if (down) {
3664         if (!mPointerSimple.down) {
3665             mPointerSimple.down = true;
3666             mPointerSimple.downTime = when;
3667 
3668             // Send down.
3669             out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
3670                                            mSource, displayId, policyFlags,
3671                                            AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState,
3672                                            mCurrentRawState.buttonState, MotionClassification::NONE,
3673                                            AMOTION_EVENT_EDGE_FLAG_NONE, 1,
3674                                            &mPointerSimple.currentProperties,
3675                                            &mPointerSimple.currentCoords, mOrientedXPrecision,
3676                                            mOrientedYPrecision, cursorPosition.x, cursorPosition.y,
3677                                            mPointerSimple.downTime, /* videoFrames */ {}));
3678         }
3679 
3680         // Send move.
3681         out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
3682                                        mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE,
3683                                        0, 0, metaState, mCurrentRawState.buttonState,
3684                                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
3685                                        &mPointerSimple.currentProperties,
3686                                        &mPointerSimple.currentCoords, mOrientedXPrecision,
3687                                        mOrientedYPrecision, cursorPosition.x, cursorPosition.y,
3688                                        mPointerSimple.downTime, /* videoFrames */ {}));
3689     }
3690 
3691     if (hovering) {
3692         if (!mPointerSimple.hovering) {
3693             mPointerSimple.hovering = true;
3694 
3695             // Send hover enter.
3696             out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
3697                                            mSource, displayId, policyFlags,
3698                                            AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
3699                                            mCurrentRawState.buttonState, MotionClassification::NONE,
3700                                            AMOTION_EVENT_EDGE_FLAG_NONE, 1,
3701                                            &mPointerSimple.currentProperties,
3702                                            &mPointerSimple.currentCoords, mOrientedXPrecision,
3703                                            mOrientedYPrecision, cursorPosition.x, cursorPosition.y,
3704                                            mPointerSimple.downTime, /* videoFrames */ {}));
3705         }
3706 
3707         // Send hover move.
3708         out.push_back(
3709                 NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
3710                                  displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
3711                                  metaState, mCurrentRawState.buttonState,
3712                                  MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
3713                                  &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
3714                                  mOrientedXPrecision, mOrientedYPrecision, cursorPosition.x,
3715                                  cursorPosition.y, mPointerSimple.downTime, /* videoFrames */ {}));
3716     }
3717 
3718     if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
3719         float vscroll = mCurrentRawState.rawVScroll;
3720         float hscroll = mCurrentRawState.rawHScroll;
3721         mWheelYVelocityControl.move(when, nullptr, &vscroll);
3722         mWheelXVelocityControl.move(when, &hscroll, nullptr);
3723 
3724         // Send scroll.
3725         PointerCoords pointerCoords;
3726         pointerCoords.copyFrom(mPointerSimple.currentCoords);
3727         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
3728         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
3729 
3730         out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
3731                                        mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL,
3732                                        0, 0, metaState, mCurrentRawState.buttonState,
3733                                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
3734                                        &mPointerSimple.currentProperties, &pointerCoords,
3735                                        mOrientedXPrecision, mOrientedYPrecision, cursorPosition.x,
3736                                        cursorPosition.y, mPointerSimple.downTime,
3737                                        /* videoFrames */ {}));
3738     }
3739 
3740     // Save state.
3741     if (down || hovering) {
3742         mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
3743         mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
3744         mPointerSimple.displayId = displayId;
3745         mPointerSimple.source = mSource;
3746         mPointerSimple.lastCursorX = cursorPosition.x;
3747         mPointerSimple.lastCursorY = cursorPosition.y;
3748     } else {
3749         mPointerSimple.reset();
3750     }
3751     return out;
3752 }
3753 
abortPointerSimple(nsecs_t when,nsecs_t readTime,uint32_t policyFlags)3754 std::list<NotifyArgs> TouchInputMapper::abortPointerSimple(nsecs_t when, nsecs_t readTime,
3755                                                            uint32_t policyFlags) {
3756     std::list<NotifyArgs> out;
3757     if (mPointerSimple.down || mPointerSimple.hovering) {
3758         int32_t metaState = getContext()->getGlobalMetaState();
3759         out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
3760                                        mPointerSimple.source, mPointerSimple.displayId, policyFlags,
3761                                        AMOTION_EVENT_ACTION_CANCEL, 0, AMOTION_EVENT_FLAG_CANCELED,
3762                                        metaState, mLastRawState.buttonState,
3763                                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
3764                                        &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
3765                                        mOrientedXPrecision, mOrientedYPrecision,
3766                                        mPointerSimple.lastCursorX, mPointerSimple.lastCursorY,
3767                                        mPointerSimple.downTime,
3768                                        /* videoFrames */ {}));
3769         if (mPointerController != nullptr) {
3770             mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
3771         }
3772     }
3773     mPointerSimple.reset();
3774     return out;
3775 }
3776 
isStylusEvent(uint32_t source,int32_t action,const PointerProperties * properties)3777 static bool isStylusEvent(uint32_t source, int32_t action, const PointerProperties* properties) {
3778     if (!isFromSource(source, AINPUT_SOURCE_STYLUS)) {
3779         return false;
3780     }
3781     const auto actionIndex = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
3782     return isStylusToolType(properties[actionIndex].toolType);
3783 }
3784 
dispatchMotion(nsecs_t when,nsecs_t readTime,uint32_t policyFlags,uint32_t source,int32_t action,int32_t actionButton,int32_t flags,int32_t metaState,int32_t buttonState,int32_t edgeFlags,const PropertiesArray & properties,const CoordsArray & coords,const IdToIndexArray & idToIndex,BitSet32 idBits,int32_t changedId,float xPrecision,float yPrecision,nsecs_t downTime,MotionClassification classification)3785 NotifyMotionArgs TouchInputMapper::dispatchMotion(
3786         nsecs_t when, nsecs_t readTime, uint32_t policyFlags, uint32_t source, int32_t action,
3787         int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
3788         int32_t edgeFlags, const PropertiesArray& properties, const CoordsArray& coords,
3789         const IdToIndexArray& idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision,
3790         float yPrecision, nsecs_t downTime, MotionClassification classification) {
3791     PointerCoords pointerCoords[MAX_POINTERS];
3792     PointerProperties pointerProperties[MAX_POINTERS];
3793     uint32_t pointerCount = 0;
3794     while (!idBits.isEmpty()) {
3795         uint32_t id = idBits.clearFirstMarkedBit();
3796         uint32_t index = idToIndex[id];
3797         pointerProperties[pointerCount].copyFrom(properties[index]);
3798         pointerCoords[pointerCount].copyFrom(coords[index]);
3799 
3800         if (changedId >= 0 && id == uint32_t(changedId)) {
3801             action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
3802         }
3803 
3804         pointerCount += 1;
3805     }
3806 
3807     ALOG_ASSERT(pointerCount != 0);
3808 
3809     if (changedId >= 0 && pointerCount == 1) {
3810         // Replace initial down and final up action.
3811         // We can compare the action without masking off the changed pointer index
3812         // because we know the index is 0.
3813         if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
3814             action = AMOTION_EVENT_ACTION_DOWN;
3815         } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
3816             if ((flags & AMOTION_EVENT_FLAG_CANCELED) != 0) {
3817                 action = AMOTION_EVENT_ACTION_CANCEL;
3818             } else {
3819                 action = AMOTION_EVENT_ACTION_UP;
3820             }
3821         } else {
3822             // Can't happen.
3823             ALOG_ASSERT(false);
3824         }
3825     }
3826     if (mCurrentStreamModifiedByExternalStylus) {
3827         source |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
3828     }
3829 
3830     const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
3831     const bool showDirectStylusPointer = mConfig.stylusPointerIconEnabled &&
3832             mDeviceMode == DeviceMode::DIRECT && isStylusEvent(source, action, pointerProperties) &&
3833             mPointerController && displayId != ADISPLAY_ID_NONE &&
3834             displayId == mPointerController->getDisplayId();
3835     if (showDirectStylusPointer) {
3836         switch (action & AMOTION_EVENT_ACTION_MASK) {
3837             case AMOTION_EVENT_ACTION_HOVER_ENTER:
3838             case AMOTION_EVENT_ACTION_HOVER_MOVE:
3839                 mPointerController->setPresentation(
3840                         PointerControllerInterface::Presentation::STYLUS_HOVER);
3841                 mPointerController
3842                         ->setPosition(mCurrentCookedState.cookedPointerData.pointerCoords[0].getX(),
3843                                       mCurrentCookedState.cookedPointerData.pointerCoords[0]
3844                                               .getY());
3845                 mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
3846                 break;
3847             case AMOTION_EVENT_ACTION_HOVER_EXIT:
3848                 mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
3849                 break;
3850         }
3851     }
3852 
3853     float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
3854     float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
3855     if (mDeviceMode == DeviceMode::POINTER) {
3856         std::tie(xCursorPosition, yCursorPosition) = mPointerController->getPosition();
3857     }
3858     const int32_t deviceId = getDeviceId();
3859     std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();
3860     std::for_each(frames.begin(), frames.end(),
3861                   [this](TouchVideoFrame& frame) { frame.rotate(this->mInputDeviceOrientation); });
3862     return NotifyMotionArgs(getContext()->getNextId(), when, readTime, deviceId, source, displayId,
3863                             policyFlags, action, actionButton, flags, metaState, buttonState,
3864                             classification, edgeFlags, pointerCount, pointerProperties,
3865                             pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
3866                             downTime, std::move(frames));
3867 }
3868 
cancelTouch(nsecs_t when,nsecs_t readTime)3869 std::list<NotifyArgs> TouchInputMapper::cancelTouch(nsecs_t when, nsecs_t readTime) {
3870     std::list<NotifyArgs> out;
3871     out += abortPointerUsage(when, readTime, /*policyFlags=*/0);
3872     out += abortTouches(when, readTime, /* policyFlags=*/0);
3873     return out;
3874 }
3875 
isPointInsidePhysicalFrame(int32_t x,int32_t y) const3876 bool TouchInputMapper::isPointInsidePhysicalFrame(int32_t x, int32_t y) const {
3877     return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue &&
3878             y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue &&
3879             isPointInRect(mPhysicalFrameInRotatedDisplay, mRawToRotatedDisplay.transform(x, y));
3880 }
3881 
findVirtualKeyHit(int32_t x,int32_t y)3882 const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
3883     for (const VirtualKey& virtualKey : mVirtualKeys) {
3884         ALOGD_IF(DEBUG_VIRTUAL_KEYS,
3885                  "VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
3886                  "left=%d, top=%d, right=%d, bottom=%d",
3887                  x, y, virtualKey.keyCode, virtualKey.scanCode, virtualKey.hitLeft,
3888                  virtualKey.hitTop, virtualKey.hitRight, virtualKey.hitBottom);
3889 
3890         if (virtualKey.isHit(x, y)) {
3891             return &virtualKey;
3892         }
3893     }
3894 
3895     return nullptr;
3896 }
3897 
assignPointerIds(const RawState & last,RawState & current)3898 void TouchInputMapper::assignPointerIds(const RawState& last, RawState& current) {
3899     uint32_t currentPointerCount = current.rawPointerData.pointerCount;
3900     uint32_t lastPointerCount = last.rawPointerData.pointerCount;
3901 
3902     current.rawPointerData.clearIdBits();
3903 
3904     if (currentPointerCount == 0) {
3905         // No pointers to assign.
3906         return;
3907     }
3908 
3909     if (lastPointerCount == 0) {
3910         // All pointers are new.
3911         for (uint32_t i = 0; i < currentPointerCount; i++) {
3912             uint32_t id = i;
3913             current.rawPointerData.pointers[i].id = id;
3914             current.rawPointerData.idToIndex[id] = i;
3915             current.rawPointerData.markIdBit(id, current.rawPointerData.isHovering(i));
3916         }
3917         return;
3918     }
3919 
3920     if (currentPointerCount == 1 && lastPointerCount == 1 &&
3921         current.rawPointerData.pointers[0].toolType == last.rawPointerData.pointers[0].toolType) {
3922         // Only one pointer and no change in count so it must have the same id as before.
3923         uint32_t id = last.rawPointerData.pointers[0].id;
3924         current.rawPointerData.pointers[0].id = id;
3925         current.rawPointerData.idToIndex[id] = 0;
3926         current.rawPointerData.markIdBit(id, current.rawPointerData.isHovering(0));
3927         return;
3928     }
3929 
3930     // General case.
3931     // We build a heap of squared euclidean distances between current and last pointers
3932     // associated with the current and last pointer indices.  Then, we find the best
3933     // match (by distance) for each current pointer.
3934     // The pointers must have the same tool type but it is possible for them to
3935     // transition from hovering to touching or vice-versa while retaining the same id.
3936     PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
3937 
3938     uint32_t heapSize = 0;
3939     for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
3940          currentPointerIndex++) {
3941         for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
3942              lastPointerIndex++) {
3943             const RawPointerData::Pointer& currentPointer =
3944                     current.rawPointerData.pointers[currentPointerIndex];
3945             const RawPointerData::Pointer& lastPointer =
3946                     last.rawPointerData.pointers[lastPointerIndex];
3947             if (currentPointer.toolType == lastPointer.toolType) {
3948                 int64_t deltaX = currentPointer.x - lastPointer.x;
3949                 int64_t deltaY = currentPointer.y - lastPointer.y;
3950 
3951                 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3952 
3953                 // Insert new element into the heap (sift up).
3954                 heap[heapSize].currentPointerIndex = currentPointerIndex;
3955                 heap[heapSize].lastPointerIndex = lastPointerIndex;
3956                 heap[heapSize].distance = distance;
3957                 heapSize += 1;
3958             }
3959         }
3960     }
3961 
3962     // Heapify
3963     for (uint32_t startIndex = heapSize / 2; startIndex != 0;) {
3964         startIndex -= 1;
3965         for (uint32_t parentIndex = startIndex;;) {
3966             uint32_t childIndex = parentIndex * 2 + 1;
3967             if (childIndex >= heapSize) {
3968                 break;
3969             }
3970 
3971             if (childIndex + 1 < heapSize &&
3972                 heap[childIndex + 1].distance < heap[childIndex].distance) {
3973                 childIndex += 1;
3974             }
3975 
3976             if (heap[parentIndex].distance <= heap[childIndex].distance) {
3977                 break;
3978             }
3979 
3980             swap(heap[parentIndex], heap[childIndex]);
3981             parentIndex = childIndex;
3982         }
3983     }
3984 
3985     if (DEBUG_POINTER_ASSIGNMENT) {
3986         ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
3987         for (size_t i = 0; i < heapSize; i++) {
3988             ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, i,
3989                   heap[i].currentPointerIndex, heap[i].lastPointerIndex, heap[i].distance);
3990         }
3991     }
3992 
3993     // Pull matches out by increasing order of distance.
3994     // To avoid reassigning pointers that have already been matched, the loop keeps track
3995     // of which last and current pointers have been matched using the matchedXXXBits variables.
3996     // It also tracks the used pointer id bits.
3997     BitSet32 matchedLastBits(0);
3998     BitSet32 matchedCurrentBits(0);
3999     BitSet32 usedIdBits(0);
4000     bool first = true;
4001     for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
4002         while (heapSize > 0) {
4003             if (first) {
4004                 // The first time through the loop, we just consume the root element of
4005                 // the heap (the one with smallest distance).
4006                 first = false;
4007             } else {
4008                 // Previous iterations consumed the root element of the heap.
4009                 // Pop root element off of the heap (sift down).
4010                 heap[0] = heap[heapSize];
4011                 for (uint32_t parentIndex = 0;;) {
4012                     uint32_t childIndex = parentIndex * 2 + 1;
4013                     if (childIndex >= heapSize) {
4014                         break;
4015                     }
4016 
4017                     if (childIndex + 1 < heapSize &&
4018                         heap[childIndex + 1].distance < heap[childIndex].distance) {
4019                         childIndex += 1;
4020                     }
4021 
4022                     if (heap[parentIndex].distance <= heap[childIndex].distance) {
4023                         break;
4024                     }
4025 
4026                     swap(heap[parentIndex], heap[childIndex]);
4027                     parentIndex = childIndex;
4028                 }
4029 
4030                 if (DEBUG_POINTER_ASSIGNMENT) {
4031                     ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
4032                     for (size_t j = 0; j < heapSize; j++) {
4033                         ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
4034                               j, heap[j].currentPointerIndex, heap[j].lastPointerIndex,
4035                               heap[j].distance);
4036                     }
4037                 }
4038             }
4039 
4040             heapSize -= 1;
4041 
4042             uint32_t currentPointerIndex = heap[0].currentPointerIndex;
4043             if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
4044 
4045             uint32_t lastPointerIndex = heap[0].lastPointerIndex;
4046             if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
4047 
4048             matchedCurrentBits.markBit(currentPointerIndex);
4049             matchedLastBits.markBit(lastPointerIndex);
4050 
4051             uint32_t id = last.rawPointerData.pointers[lastPointerIndex].id;
4052             current.rawPointerData.pointers[currentPointerIndex].id = id;
4053             current.rawPointerData.idToIndex[id] = currentPointerIndex;
4054             current.rawPointerData.markIdBit(id,
4055                                              current.rawPointerData.isHovering(
4056                                                      currentPointerIndex));
4057             usedIdBits.markBit(id);
4058 
4059             ALOGD_IF(DEBUG_POINTER_ASSIGNMENT,
4060                      "assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32 ", id=%" PRIu32
4061                      ", distance=%" PRIu64,
4062                      lastPointerIndex, currentPointerIndex, id, heap[0].distance);
4063             break;
4064         }
4065     }
4066 
4067     // Assign fresh ids to pointers that were not matched in the process.
4068     for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
4069         uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
4070         uint32_t id = usedIdBits.markFirstUnmarkedBit();
4071 
4072         current.rawPointerData.pointers[currentPointerIndex].id = id;
4073         current.rawPointerData.idToIndex[id] = currentPointerIndex;
4074         current.rawPointerData.markIdBit(id,
4075                                          current.rawPointerData.isHovering(currentPointerIndex));
4076 
4077         ALOGD_IF(DEBUG_POINTER_ASSIGNMENT,
4078                  "assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex,
4079                  id);
4080     }
4081 }
4082 
getKeyCodeState(uint32_t sourceMask,int32_t keyCode)4083 int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
4084     if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
4085         return AKEY_STATE_VIRTUAL;
4086     }
4087 
4088     for (const VirtualKey& virtualKey : mVirtualKeys) {
4089         if (virtualKey.keyCode == keyCode) {
4090             return AKEY_STATE_UP;
4091         }
4092     }
4093 
4094     return AKEY_STATE_UNKNOWN;
4095 }
4096 
getScanCodeState(uint32_t sourceMask,int32_t scanCode)4097 int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
4098     if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
4099         return AKEY_STATE_VIRTUAL;
4100     }
4101 
4102     for (const VirtualKey& virtualKey : mVirtualKeys) {
4103         if (virtualKey.scanCode == scanCode) {
4104             return AKEY_STATE_UP;
4105         }
4106     }
4107 
4108     return AKEY_STATE_UNKNOWN;
4109 }
4110 
markSupportedKeyCodes(uint32_t sourceMask,const std::vector<int32_t> & keyCodes,uint8_t * outFlags)4111 bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask,
4112                                              const std::vector<int32_t>& keyCodes,
4113                                              uint8_t* outFlags) {
4114     for (const VirtualKey& virtualKey : mVirtualKeys) {
4115         for (size_t i = 0; i < keyCodes.size(); i++) {
4116             if (virtualKey.keyCode == keyCodes[i]) {
4117                 outFlags[i] = 1;
4118             }
4119         }
4120     }
4121 
4122     return true;
4123 }
4124 
getAssociatedDisplayId()4125 std::optional<int32_t> TouchInputMapper::getAssociatedDisplayId() {
4126     if (mParameters.hasAssociatedDisplay) {
4127         if (mDeviceMode == DeviceMode::POINTER) {
4128             return std::make_optional(mPointerController->getDisplayId());
4129         } else {
4130             return std::make_optional(mViewport.displayId);
4131         }
4132     }
4133     return std::nullopt;
4134 }
4135 
4136 } // namespace android
4137