Add pointer capture eligibility native APIs

Bug: 202273865
Test: manual
Change-Id: I98a31f4cae1a12f45f789cb1344a258e3de30317
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 3f3c0db..441a1de 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -5645,6 +5645,15 @@
             return;
         }
 
+        if (enabled) {
+            if (std::find(mIneligibleDisplaysForPointerCapture.begin(),
+                          mIneligibleDisplaysForPointerCapture.end(),
+                          mFocusedDisplayId) != mIneligibleDisplaysForPointerCapture.end()) {
+                ALOGW("Ignoring request to enable Pointer Capture: display is not eligible");
+                return;
+            }
+        }
+
         setPointerCaptureLocked(enabled);
     } // release lock
 
@@ -5652,6 +5661,16 @@
     mLooper->wake();
 }
 
+void InputDispatcher::setDisplayEligibilityForPointerCapture(int32_t displayId, bool isEligible) {
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+        std::erase(mIneligibleDisplaysForPointerCapture, displayId);
+        if (!isEligible) {
+            mIneligibleDisplaysForPointerCapture.push_back(displayId);
+        }
+    } // release lock
+}
+
 std::optional<int32_t> InputDispatcher::findGestureMonitorDisplayByTokenLocked(
         const sp<IBinder>& token) {
     for (const auto& it : mGestureMonitorsByDisplay) {
@@ -6311,6 +6330,8 @@
         // Call focus resolver to clean up stale requests. This must be called after input windows
         // have been removed for the removed display.
         mFocusResolver.displayRemoved(displayId);
+        // Reset pointer capture eligibility, regardless of previous state.
+        std::erase(mIneligibleDisplaysForPointerCapture, displayId);
     } // release lock
 
     // Wake up poll loop since it may need to make new input dispatching choices.
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index cbb7bad..7564839 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -136,6 +136,7 @@
     status_t pilferPointers(const sp<IBinder>& token) override;
     void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) override;
     bool flushSensor(int deviceId, InputDeviceSensorType sensorType) override;
+    void setDisplayEligibilityForPointerCapture(int displayId, bool isEligible) override;
 
     std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const;
 
@@ -420,6 +421,10 @@
     // This should be in sync with PointerCaptureChangedEvents dispatched to the input channel.
     sp<IBinder> mWindowTokenWithPointerCapture GUARDED_BY(mLock);
 
+    // Displays that are ineligible for pointer capture.
+    // TODO(b/214621487): Remove or move to a display flag.
+    std::vector<int32_t> mIneligibleDisplaysForPointerCapture GUARDED_BY(mLock);
+
     // Disable Pointer Capture as a result of loss of window focus.
     void disablePointerCaptureForcedLocked() REQUIRES(mLock);
 
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index c469ec3..16a6f16 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -201,6 +201,13 @@
      */
     virtual void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) = 0;
 
+    /**
+     * Sets the eligibility of a given display to enable pointer capture. If a display is marked
+     * ineligible, all attempts to request pointer capture for windows on that display will fail.
+     *  TODO(b/214621487): Remove or move to a display flag.
+     */
+    virtual void setDisplayEligibilityForPointerCapture(int displayId, bool isEligible) = 0;
+
     /* Flush input device motion sensor.
      *
      * Returns true on success.