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