Use WindowInfosListener instead of SF reporting to IF

1. Moved ISetInputWindowsListener and renamed to
IWindowInfosReportedListener to be more generic

2. Updated SurfaceFlinger so it reports window infos changed instead of
directly reporting window info to InputManager

Test: Existing tests pass
Test: WindowInfosListenerTest
Bug: 188792659
Change-Id: Ia8e688652663734aa01d008c2f524c6cf4971e17
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a2e7ccb..3616240 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -31,7 +31,6 @@
 #include <android/hardware/configstore/1.1/types.h>
 #include <android/hardware/power/Boost.h>
 #include <android/native_window.h>
-#include <android/os/BnSetInputWindowsListener.h>
 #include <android/os/IInputFlinger.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
@@ -277,21 +276,6 @@
 
 }  // namespace anonymous
 
-struct SetInputWindowsListener : os::BnSetInputWindowsListener {
-    explicit SetInputWindowsListener(std::function<void()> listenerCb) : mListenerCb(listenerCb) {}
-
-    binder::Status onSetInputWindowsFinished() override;
-
-    std::function<void()> mListenerCb;
-};
-
-binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {
-    if (mListenerCb != nullptr) {
-        mListenerCb();
-    }
-    return binder::Status::ok();
-}
-
 // ---------------------------------------------------------------------------
 
 const String16 sHardwareTest("android.permission.HARDWARE_TEST");
@@ -358,10 +342,8 @@
         mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
         mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
         mPowerAdvisor(*this),
-        mWindowInfosListenerInvoker(new WindowInfosListenerInvoker()) {
+        mWindowInfosListenerInvoker(new WindowInfosListenerInvoker(this)) {
     ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
-
-    mSetInputWindowsListener = new SetInputWindowsListener([&]() { setInputWindowsFinished(); });
 }
 
 SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {
@@ -3058,11 +3040,11 @@
 
     if (mVisibleRegionsDirty || mInputInfoChanged) {
         mInputInfoChanged = false;
-        updateInputWindowInfo();
+        notifyWindowInfos();
     } else if (mInputWindowCommands.syncInputWindows) {
         // If the caller requested to sync input windows, but there are no
         // changes to input windows, notify immediately.
-        setInputWindowsFinished();
+        windowInfosReported();
     }
 
     for (const auto& focusRequest : mInputWindowCommands.focusRequests) {
@@ -3077,8 +3059,8 @@
     return value;
 }
 
-void SurfaceFlinger::updateInputWindowInfo() {
-    std::vector<WindowInfo> inputInfos;
+void SurfaceFlinger::notifyWindowInfos() {
+    std::vector<WindowInfo> windowInfos;
 
     mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
         if (!layer->needsInputInfo()) return;
@@ -3087,12 +3069,10 @@
                 : nullptr;
         // When calculating the screen bounds we ignore the transparent region since it may
         // result in an unwanted offset.
-        inputInfos.push_back(layer->fillInputInfo(display));
+        windowInfos.push_back(layer->fillInputInfo(display));
     });
-
-    mInputFlinger->setInputWindows(inputInfos,
-                               mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
-                                                                     : nullptr);
+    mWindowInfosListenerInvoker->windowInfosChanged(windowInfos,
+                                                    mInputWindowCommands.syncInputWindows);
 }
 
 void SurfaceFlinger::updateCursorAsync() {
@@ -6444,7 +6424,7 @@
     return NO_ERROR;
 }
 
-void SurfaceFlinger::setInputWindowsFinished() {
+void SurfaceFlinger::windowInfosReported() {
     Mutex::Autolock _l(mStateLock);
     signalSynchronousTransactions(CountDownLatch::eSyncInputWindows);
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b2e5e7d..c428c37 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -93,7 +93,6 @@
 class TunnelModeEnabledReporter;
 class HdrLayerInfoReporter;
 class HWComposer;
-struct SetInputWindowsListener;
 class IGraphicBufferProducer;
 class Layer;
 class MessageBase;
@@ -334,7 +333,7 @@
     // If set, disables reusing client composition buffers. This can be set by
     // debug.sf.disable_client_composition_cache
     bool mDisableClientCompositionCache = false;
-    void setInputWindowsFinished();
+    void windowInfosReported();
 
     // Disables expensive rendering for all displays
     // This is scheduled on the main thread
@@ -822,7 +821,7 @@
     void handleTransactionLocked(uint32_t transactionFlags) REQUIRES(mStateLock);
 
     void updateInputFlinger();
-    void updateInputWindowInfo();
+    void notifyWindowInfos();
     void commitInputWindowCommands() REQUIRES(mStateLock);
     void updateCursorAsync();
 
@@ -1448,8 +1447,6 @@
     // Should only be accessed by the main thread.
     InputWindowCommands mInputWindowCommands;
 
-    sp<SetInputWindowsListener> mSetInputWindowsListener;
-
     Hwc2::impl::PowerAdvisor mPowerAdvisor;
 
     // This should only be accessed on the main thread.
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
index 55136fb..dc2aa58 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
@@ -17,12 +17,32 @@
 #include "WindowInfosListenerInvoker.h"
 #include <gui/ISurfaceComposer.h>
 #include <unordered_set>
+#include "SurfaceFlinger.h"
 
 namespace android {
 
 using gui::IWindowInfosListener;
 using gui::WindowInfo;
 
+struct WindowInfosReportedListener : gui::BnWindowInfosReportedListener {
+    explicit WindowInfosReportedListener(std::function<void()> listenerCb)
+          : mListenerCb(listenerCb) {}
+
+    binder::Status onWindowInfosReported() override {
+        if (mListenerCb != nullptr) {
+            mListenerCb();
+        }
+        return binder::Status::ok();
+    }
+
+    std::function<void()> mListenerCb;
+};
+
+WindowInfosListenerInvoker::WindowInfosListenerInvoker(const sp<SurfaceFlinger>& sf) : mSf(sf) {
+    mWindowInfosReportedListener =
+            new WindowInfosReportedListener([&]() { windowInfosReported(); });
+}
+
 void WindowInfosListenerInvoker::addWindowInfosListener(
         const sp<IWindowInfosListener>& windowInfosListener) {
     sp<IBinder> asBinder = IInterface::asBinder(windowInfosListener);
@@ -46,7 +66,8 @@
     mWindowInfosListeners.erase(who);
 }
 
-void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos) {
+void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos,
+                                                    bool shouldSync) {
     std::unordered_set<sp<IWindowInfosListener>, ISurfaceComposer::SpHash<IWindowInfosListener>>
             windowInfosListeners;
 
@@ -57,8 +78,18 @@
         }
     }
 
+    mCallbacksPending = windowInfosListeners.size();
+
     for (const auto& listener : windowInfosListeners) {
-        listener->onWindowInfosChanged(windowInfos);
+        listener->onWindowInfosChanged(windowInfos,
+                                       shouldSync ? mWindowInfosReportedListener : nullptr);
+    }
+}
+
+void WindowInfosListenerInvoker::windowInfosReported() {
+    mCallbacksPending--;
+    if (mCallbacksPending == 0) {
+        mSf->windowInfosReported();
     }
 }
 
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h
index b979de1..5e5796f 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.h
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.h
@@ -16,32 +16,42 @@
 
 #pragma once
 
+#include <android/gui/BnWindowInfosReportedListener.h>
 #include <android/gui/IWindowInfosListener.h>
+#include <android/gui/IWindowInfosReportedListener.h>
 #include <binder/IBinder.h>
 #include <utils/Mutex.h>
 #include <unordered_map>
 
 namespace android {
 
+class SurfaceFlinger;
+
 class WindowInfosListenerInvoker : public IBinder::DeathRecipient {
 public:
+    WindowInfosListenerInvoker(const sp<SurfaceFlinger>& sf);
     void addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
     void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
 
-    void windowInfosChanged(const std::vector<gui::WindowInfo>& windowInfos);
+    void windowInfosChanged(const std::vector<gui::WindowInfo>& windowInfos, bool shouldSync);
 
 protected:
     void binderDied(const wp<IBinder>& who) override;
 
 private:
+    void windowInfosReported();
+
     struct WpHash {
         size_t operator()(const wp<IBinder>& p) const {
             return std::hash<IBinder*>()(p.unsafe_get());
         }
     };
 
+    const sp<SurfaceFlinger> mSf;
     std::mutex mListenersMutex;
     std::unordered_map<wp<IBinder>, const sp<gui::IWindowInfosListener>, WpHash>
             mWindowInfosListeners GUARDED_BY(mListenersMutex);
+    sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener;
+    std::atomic<size_t> mCallbacksPending{0};
 };
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index b96725f..26c91fa 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -51,6 +51,7 @@
         "Stress_test.cpp",
         "SurfaceInterceptor_test.cpp",
         "VirtualDisplay_test.cpp",
+        "WindowInfosListener_test.cpp",
     ],
     data: ["SurfaceFlinger_test.filter"],
     static_libs: [
diff --git a/services/surfaceflinger/tests/WindowInfosListener_test.cpp b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
new file mode 100644
index 0000000..89228d5
--- /dev/null
+++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gui/SurfaceComposerClient.h>
+#include <private/android_filesystem_config.h>
+#include <future>
+#include "utils/TransactionUtils.h"
+
+namespace android {
+using Transaction = SurfaceComposerClient::Transaction;
+using gui::WindowInfo;
+
+class WindowInfosListenerTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        seteuid(AID_SYSTEM);
+        mClient = new SurfaceComposerClient;
+        mWindowInfosListener = new SyncWindowInfosListener();
+        mClient->addWindowInfosListener(mWindowInfosListener);
+    }
+
+    void TearDown() override {
+        mClient->removeWindowInfosListener(mWindowInfosListener);
+        seteuid(AID_ROOT);
+    }
+
+    struct SyncWindowInfosListener : public gui::WindowInfosListener {
+    public:
+        void onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos) override {
+            windowInfosPromise.set_value(windowInfos);
+        }
+
+        std::vector<WindowInfo> waitForWindowInfos() {
+            std::future<std::vector<WindowInfo>> windowInfosFuture =
+                    windowInfosPromise.get_future();
+            std::vector<WindowInfo> windowInfos = windowInfosFuture.get();
+            windowInfosPromise = std::promise<std::vector<WindowInfo>>();
+            return windowInfos;
+        }
+
+    private:
+        std::promise<std::vector<WindowInfo>> windowInfosPromise;
+    };
+
+    sp<SurfaceComposerClient> mClient;
+    sp<SyncWindowInfosListener> mWindowInfosListener;
+};
+
+std::optional<WindowInfo> findMatchingWindowInfo(WindowInfo targetWindowInfo,
+                                                 std::vector<WindowInfo> windowInfos) {
+    std::optional<WindowInfo> foundWindowInfo = std::nullopt;
+    for (WindowInfo windowInfo : windowInfos) {
+        if (windowInfo.token == targetWindowInfo.token) {
+            foundWindowInfo = std::make_optional<>(windowInfo);
+            break;
+        }
+    }
+
+    return foundWindowInfo;
+}
+
+TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) {
+    std::string name = "Test Layer";
+    sp<IBinder> token = new BBinder();
+    WindowInfo windowInfo;
+    windowInfo.name = name;
+    windowInfo.token = token;
+    sp<SurfaceControl> surfaceControl =
+            mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
+                                   ISurfaceComposerClient::eFXSurfaceBufferState);
+
+    Transaction()
+            .setLayerStack(surfaceControl, 0)
+            .show(surfaceControl)
+            .setLayer(surfaceControl, INT32_MAX - 1)
+            .setInputWindowInfo(surfaceControl, windowInfo)
+            .apply();
+
+    std::vector<WindowInfo> windowInfos = mWindowInfosListener->waitForWindowInfos();
+    std::optional<WindowInfo> foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
+    ASSERT_NE(std::nullopt, foundWindowInfo);
+
+    Transaction().reparent(surfaceControl, nullptr).apply();
+
+    windowInfos = mWindowInfosListener->waitForWindowInfos();
+    foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
+    ASSERT_EQ(std::nullopt, foundWindowInfo);
+}
+
+TEST_F(WindowInfosListenerTest, WindowInfoChanged) {
+    std::string name = "Test Layer";
+    sp<IBinder> token = new BBinder();
+    WindowInfo windowInfo;
+    windowInfo.name = name;
+    windowInfo.token = token;
+    sp<SurfaceControl> surfaceControl =
+            mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
+                                   ISurfaceComposerClient::eFXSurfaceBufferState);
+
+    Transaction()
+            .setLayerStack(surfaceControl, 0)
+            .show(surfaceControl)
+            .setLayer(surfaceControl, INT32_MAX - 1)
+            .setInputWindowInfo(surfaceControl, windowInfo)
+            .apply();
+
+    std::vector<WindowInfo> windowInfos = mWindowInfosListener->waitForWindowInfos();
+    std::optional<WindowInfo> foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
+    ASSERT_NE(std::nullopt, foundWindowInfo);
+    ASSERT_TRUE(foundWindowInfo->touchableRegion.isEmpty());
+
+    Rect touchableRegions(0, 0, 50, 50);
+    windowInfo.addTouchableRegion(Rect(0, 0, 50, 50));
+    Transaction().setInputWindowInfo(surfaceControl, windowInfo).apply();
+
+    windowInfos = mWindowInfosListener->waitForWindowInfos();
+    foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
+    ASSERT_NE(std::nullopt, foundWindowInfo);
+    ASSERT_TRUE(foundWindowInfo->touchableRegion.hasSameRects(windowInfo.touchableRegion));
+}
+
+} // namespace android