Merge "SurfaceFlinger: Cache updateInputWindows call" into rvc-dev
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d7ec868..e4d754c 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -485,6 +485,10 @@
         }
     }
 
+    if (recomputeVisibleRegions == true) {
+        maybeDirtyInput();
+    }
+
     return true;
 }
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 64cfb3d..3765d0d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -993,6 +993,9 @@
     commitTransaction(c);
     mPendingStatesSnapshot = mPendingStates;
     mCurrentState.callbackHandles = {};
+
+    maybeDirtyInput();
+
     return flags;
 }
 
@@ -2472,6 +2475,32 @@
     }
 }
 
+bool Layer::maybeDirtyInput() {
+    // No sense redirtying input.
+    if (mFlinger->inputDirty()) return true;
+
+    if (hasInput()) {
+        mFlinger->dirtyInput();
+        return true;
+    }
+
+    // If a child or relative dirties the input, no sense continuing to traverse
+    // so we return early and halt the recursion. We traverse ourselves instead
+    // of using traverse() so we can implement this early halt.
+    for (const sp<Layer>& child : mDrawingChildren) {
+        if (child->maybeDirtyInput()) {
+            return true;
+        }
+    }
+    for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
+        sp<Layer> relative = weakRelative.promote();
+        if (relative && relative->maybeDirtyInput()) {
+            return true;
+        }
+    }
+    return false;
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 20d7232..e21a866 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -997,6 +997,10 @@
     // Window types from WindowManager.LayoutParams
     const int mWindowType;
 
+    // Called when mDrawingState has changed. If we or one of our children/relatives hasInput()
+    // then we will dirty the setInputWindows cache.
+    bool maybeDirtyInput();
+
 private:
     /**
      * Returns an unsorted vector of all layers that are part of this tree.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e764d24..ffb8ae9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2779,6 +2779,19 @@
 void SurfaceFlinger::updateInputWindowInfo() {
     std::vector<InputWindowInfo> inputHandles;
 
+    // We use a simple caching algorithm here. mInputDirty begins as true,
+    // after we call setInputWindows we set it to false, so
+    // in the future we wont call it again.. We set input dirty to true again
+    // when any layer that hasInput() has a transaction performed on it
+    // or when any parent or relative parent of such a layer has a transaction
+    // performed on it. Not all of these transactions will really result in
+    // input changes but all input changes will spring from these transactions
+    // so the cache is safe but not optimal. It seems like it might be annoyingly
+    // costly to cache and comapre the actual InputWindowHandle vector though.
+    if (!mInputDirty) {
+        return;
+    }
+
     mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
         if (layer->hasInput()) {
             // When calculating the screen bounds we ignore the transparent region since it may
@@ -2790,6 +2803,8 @@
     mInputFlinger->setInputWindows(inputHandles,
                                    mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
                                                                          : nullptr);
+
+    mInputDirty = false;
 }
 
 void SurfaceFlinger::commitInputWindowCommands() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e7f9930..a157a06 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1235,6 +1235,11 @@
     // janky frames there are.
     nsecs_t mMissedFrameJankStart = 0;
     int32_t mMissedFrameJankCount = 0;
+
+    // See updateInputWindowInfo() for details
+    std::atomic<bool> mInputDirty = true;
+    void dirtyInput() { mInputDirty = true; }
+    bool inputDirty() { return mInputDirty; }
 };
 
 } // namespace android