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