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