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