Change isStylusEvent behaviour

This function is now getting moved to Input.h.

We are also making its behaviour deterministic: if at least one pointer
is stylus, then the event is a stylus event (unless the source wasn't
set to "stylus").

This way, an event with 1 finger and 1 stylus pointers will have the
same consistent behaviour, regardless of the order that the pointers are
stored inside the event.

Bug: 211379801
Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST
Change-Id: Ie164e32b7c0e9cf21b3819b01a03ac2885666191
diff --git a/include/input/Input.h b/include/input/Input.h
index 567361d..bd544b5 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -257,6 +257,10 @@
 
 bool isStylusToolType(ToolType toolType);
 
+struct PointerProperties;
+
+bool isStylusEvent(uint32_t source, const std::vector<PointerProperties>& properties);
+
 /*
  * Flags that flow alongside events in the input dispatch system to help with certain
  * policy decisions such as waking from device sleep.
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index c127411..bd5b67b 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -217,6 +217,19 @@
     return toolType == ToolType::STYLUS || toolType == ToolType::ERASER;
 }
 
+bool isStylusEvent(uint32_t source, const std::vector<PointerProperties>& properties) {
+    if (!isFromSource(source, AINPUT_SOURCE_STYLUS)) {
+        return false;
+    }
+    // Need at least one stylus pointer for this event to be considered a stylus event
+    for (const PointerProperties& pointerProperties : properties) {
+        if (isStylusToolType(pointerProperties.toolType)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 VerifiedKeyEvent verifiedKeyEventFromKeyEvent(const KeyEvent& event) {
     return {{VerifiedInputEvent::Type::KEY, event.getDeviceId(), event.getEventTime(),
              event.getSource(), event.getDisplayId()},
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 90bd7c9..3c26d1d 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -3782,34 +3782,26 @@
     return out;
 }
 
-static bool isStylusEvent(uint32_t source, int32_t action, const PointerProperties* properties) {
-    if (!isFromSource(source, AINPUT_SOURCE_STYLUS)) {
-        return false;
-    }
-    const auto actionIndex = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-    return isStylusToolType(properties[actionIndex].toolType);
-}
-
 NotifyMotionArgs TouchInputMapper::dispatchMotion(
         nsecs_t when, nsecs_t readTime, uint32_t policyFlags, uint32_t source, int32_t action,
         int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
         int32_t edgeFlags, const PropertiesArray& properties, const CoordsArray& coords,
         const IdToIndexArray& idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision,
         float yPrecision, nsecs_t downTime, MotionClassification classification) {
-    PointerCoords pointerCoords[MAX_POINTERS];
-    PointerProperties pointerProperties[MAX_POINTERS];
+    std::vector<PointerCoords> pointerCoords;
+    std::vector<PointerProperties> pointerProperties;
     uint32_t pointerCount = 0;
     while (!idBits.isEmpty()) {
         uint32_t id = idBits.clearFirstMarkedBit();
         uint32_t index = idToIndex[id];
-        pointerProperties[pointerCount] = properties[index];
-        pointerCoords[pointerCount] = coords[index];
+        pointerProperties.push_back(properties[index]);
+        pointerCoords.push_back(coords[index]);
 
         if (changedId >= 0 && id == uint32_t(changedId)) {
             action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
         }
 
-        pointerCount += 1;
+        pointerCount++;
     }
 
     ALOG_ASSERT(pointerCount != 0);
@@ -3837,7 +3829,7 @@
 
     const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
     const bool showDirectStylusPointer = mConfig.stylusPointerIconEnabled &&
-            mDeviceMode == DeviceMode::DIRECT && isStylusEvent(source, action, pointerProperties) &&
+            mDeviceMode == DeviceMode::DIRECT && isStylusEvent(source, pointerProperties) &&
             mPointerController && displayId != ADISPLAY_ID_NONE &&
             displayId == mPointerController->getDisplayId();
     if (showDirectStylusPointer) {
@@ -3869,9 +3861,9 @@
                   [this](TouchVideoFrame& frame) { frame.rotate(this->mInputDeviceOrientation); });
     return NotifyMotionArgs(getContext()->getNextId(), when, readTime, deviceId, source, displayId,
                             policyFlags, action, actionButton, flags, metaState, buttonState,
-                            classification, edgeFlags, pointerCount, pointerProperties,
-                            pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
-                            downTime, std::move(frames));
+                            classification, edgeFlags, pointerCount, pointerProperties.data(),
+                            pointerCoords.data(), xPrecision, yPrecision, xCursorPosition,
+                            yCursorPosition, downTime, std::move(frames));
 }
 
 std::list<NotifyArgs> TouchInputMapper::cancelTouch(nsecs_t when, nsecs_t readTime) {