Input devices configure on per-display basis (1/2)

A InputDevice may be associated with a specific display.
This would provide a function to check if an input device can dispatch
input events to the specific display.
If the device has no associated, the events can dispatch to any display.

Bug: 116767202
Test: atest -a libinput_tests inputflinger_tests
Change-Id: I05a1c8db191ef1e6c4182f902a7a3b51e420740d
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 64070e3..f84aa34 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -805,6 +805,30 @@
     return false;
 }
 
+bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) {
+    AutoMutex _l(mLock);
+
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex < 0) {
+        ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
+        return false;
+    }
+
+    InputDevice* device = mDevices.valueAt(deviceIndex);
+    std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplay();
+    // No associated display. By default, can dispatch to all displays.
+    if (!associatedDisplayId) {
+        return true;
+    }
+
+    if (*associatedDisplayId == ADISPLAY_ID_NONE) {
+        ALOGW("Device has associated, but no associated display id.");
+        return true;
+    }
+
+    return *associatedDisplayId == displayId;
+}
+
 void InputReader::dump(std::string& dump) {
     AutoMutex _l(mLock);
 
@@ -1275,6 +1299,18 @@
     mContext->getListener()->notifyDeviceReset(&args);
 }
 
+std::optional<int32_t> InputDevice::getAssociatedDisplay() {
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay();
+        if (associatedDisplayId) {
+            return associatedDisplayId;
+        }
+    }
+
+    return std::nullopt;
+}
 
 // --- CursorButtonAccumulator ---
 
@@ -2647,7 +2683,7 @@
         }
 
         // Update the PointerController if viewports changed.
-        if (mParameters.hasAssociatedDisplay) {
+        if (mParameters.mode == Parameters::MODE_POINTER) {
             getPolicy()->obtainPointerController(getDeviceId());
         }
         bumpGeneration();
@@ -2919,6 +2955,19 @@
     }
 }
 
+std::optional<int32_t> CursorInputMapper::getAssociatedDisplay() {
+    if (mParameters.hasAssociatedDisplay) {
+        if (mParameters.mode == Parameters::MODE_POINTER) {
+            return std::make_optional(mPointerController->getDisplayId());
+        } else {
+            // If the device is orientationAware and not a mouse,
+            // it expects to dispatch events to any display
+            return std::make_optional(ADISPLAY_ID_NONE);
+        }
+    }
+    return std::nullopt;
+}
+
 // --- RotaryEncoderInputMapper ---
 
 RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
@@ -6511,9 +6560,7 @@
             ALOG_ASSERT(false);
         }
     }
-    const int32_t displayId = mPointerController != nullptr ?
-            mPointerController->getDisplayId() : mViewport.displayId;
-
+    const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE);
     const int32_t deviceId = getDeviceId();
     std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
     NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId,
@@ -6830,6 +6877,16 @@
     return true;
 }
 
+std::optional<int32_t> TouchInputMapper::getAssociatedDisplay() {
+    if (mParameters.hasAssociatedDisplay) {
+        if (mDeviceMode == DEVICE_MODE_POINTER) {
+            return std::make_optional(mPointerController->getDisplayId());
+        } else {
+            return std::make_optional(mViewport.displayId);
+        }
+    }
+    return std::nullopt;
+}
 
 // --- SingleTouchInputMapper ---