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