Added IWindowInfosChangedListener interface

Added WindowInfosChangedListener interface and the ability to
register a WindowInfosChangedListener in SCC. Also added the
SurfaceFlinger code where the WindowInfosChangedListener gets
registered and reports to the listeners.

Test: Existing tests pass
Bug: 188792659
Change-Id: If7b93df0afd71a88ea703d2113e68bfb549368af
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 2d8fff9..4f57d57 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -67,6 +67,7 @@
         ":guiconstants_aidl",
         "android/gui/FocusRequest.aidl",
         "android/gui/InputApplicationInfo.aidl",
+        "android/gui/IWindowInfosListener.aidl",
         "android/gui/WindowInfo.aidl",
         "WindowInfo.cpp",
     ],
@@ -189,6 +190,7 @@
         "SyncFeatures.cpp",
         "TransactionTracing.cpp",
         "view/Surface.cpp",
+        "WindowInfosListenerReporter.cpp",
         "bufferqueue/1.0/B2HProducerListener.cpp",
         "bufferqueue/1.0/H2BGraphicBufferProducer.cpp",
         "bufferqueue/2.0/B2HProducerListener.cpp",
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 5023b6b..2930154 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -34,7 +34,6 @@
 #include <gui/BufferQueueCore.h>
 #include <gui/IConsumerListener.h>
 #include <gui/IProducerListener.h>
-#include <gui/ISurfaceComposer.h>
 #include <private/gui/ComposerService.h>
 
 #include <system/window.h>
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 0d7795e..2a980bd 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -44,6 +44,7 @@
 
 namespace android {
 
+using gui::IWindowInfosListener;
 using ui::ColorMode;
 
 class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
@@ -1227,6 +1228,22 @@
 
         return reply.readInt32(buffers);
     }
+
+    status_t addWindowInfosListener(
+            const sp<IWindowInfosListener>& windowInfosListener) const override {
+        Parcel data, reply;
+        SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
+        SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(windowInfosListener));
+        return remote()->transact(BnSurfaceComposer::ADD_WINDOW_INFOS_LISTENER, data, &reply);
+    }
+
+    status_t removeWindowInfosListener(
+            const sp<IWindowInfosListener>& windowInfosListener) const override {
+        Parcel data, reply;
+        SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
+        SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(windowInfosListener));
+        return remote()->transact(BnSurfaceComposer::REMOVE_WINDOW_INFOS_LISTENER, data, &reply);
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -2107,6 +2124,20 @@
             SAFE_PARCEL(reply->writeBool, success);
             return err;
         }
+        case ADD_WINDOW_INFOS_LISTENER: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IWindowInfosListener> listener;
+            SAFE_PARCEL(data.readStrongBinder, &listener);
+
+            return addWindowInfosListener(listener);
+        }
+        case REMOVE_WINDOW_INFOS_LISTENER: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IWindowInfosListener> listener;
+            SAFE_PARCEL(data.readStrongBinder, &listener);
+
+            return removeWindowInfosListener(listener);
+        }
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index c52c644..8547739 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -19,6 +19,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <android/gui/IWindowInfosListener.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/SortedVector.h>
@@ -54,6 +55,7 @@
 using gui::FocusRequest;
 using gui::WindowInfo;
 using gui::WindowInfoHandle;
+using gui::WindowInfosListener;
 using ui::ColorMode;
 // ---------------------------------------------------------------------------
 
@@ -95,6 +97,7 @@
     if (instance.mComposerService == nullptr) {
         if (ComposerService::getInstance().connectLocked()) {
             ALOGD("ComposerService reconnected");
+            WindowInfosListenerReporter::getInstance()->reconnect(instance.mComposerService);
         }
     }
     return instance.mComposerService;
@@ -1768,15 +1771,10 @@
 
 // ---------------------------------------------------------------------------
 
-SurfaceComposerClient::SurfaceComposerClient()
-    : mStatus(NO_INIT)
-{
-}
+SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT) {}
 
 SurfaceComposerClient::SurfaceComposerClient(const sp<ISurfaceComposerClient>& client)
-    : mStatus(NO_ERROR), mClient(client)
-{
-}
+      : mStatus(NO_ERROR), mClient(client) {}
 
 void SurfaceComposerClient::onFirstRef() {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
@@ -2142,6 +2140,18 @@
     return ComposerService::getComposerService()->getGPUContextPriority();
 }
 
+status_t SurfaceComposerClient::addWindowInfosListener(
+        const sp<WindowInfosListener>& windowInfosListener) {
+    return WindowInfosListenerReporter::getInstance()
+            ->addWindowInfosListener(windowInfosListener, ComposerService::getComposerService());
+}
+
+status_t SurfaceComposerClient::removeWindowInfosListener(
+        const sp<WindowInfosListener>& windowInfosListener) {
+    return WindowInfosListenerReporter::getInstance()
+            ->removeWindowInfosListener(windowInfosListener, ComposerService::getComposerService());
+}
+
 // ----------------------------------------------------------------------------
 
 status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs,
diff --git a/libs/gui/WindowInfosListenerReporter.cpp b/libs/gui/WindowInfosListenerReporter.cpp
new file mode 100644
index 0000000..834e2b8
--- /dev/null
+++ b/libs/gui/WindowInfosListenerReporter.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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 <gui/ISurfaceComposer.h>
+#include <gui/WindowInfosListenerReporter.h>
+
+namespace android {
+
+using gui::WindowInfo;
+using gui::WindowInfosListener;
+
+sp<WindowInfosListenerReporter> WindowInfosListenerReporter::getInstance() {
+    static sp<WindowInfosListenerReporter> sInstance = new WindowInfosListenerReporter;
+    return sInstance;
+}
+
+status_t WindowInfosListenerReporter::addWindowInfosListener(
+        const sp<WindowInfosListener>& windowInfosListener,
+        const sp<ISurfaceComposer>& surfaceComposer) {
+    status_t status = OK;
+    {
+        std::scoped_lock lock(mListenersMutex);
+        if (mWindowInfosListeners.empty()) {
+            status = surfaceComposer->addWindowInfosListener(this);
+        }
+
+        if (status == OK) {
+            mWindowInfosListeners.insert(windowInfosListener);
+        }
+    }
+
+    return status;
+}
+
+status_t WindowInfosListenerReporter::removeWindowInfosListener(
+        const sp<WindowInfosListener>& windowInfosListener,
+        const sp<ISurfaceComposer>& surfaceComposer) {
+    status_t status = OK;
+    {
+        std::scoped_lock lock(mListenersMutex);
+        if (mWindowInfosListeners.size() == 1) {
+            status = surfaceComposer->removeWindowInfosListener(this);
+        }
+
+        if (status == OK) {
+            mWindowInfosListeners.erase(windowInfosListener);
+        }
+    }
+
+    return status;
+}
+
+binder::Status WindowInfosListenerReporter::onWindowInfosChanged(
+        const std::vector<WindowInfo>& windowInfos) {
+    std::unordered_set<sp<WindowInfosListener>, ISurfaceComposer::SpHash<WindowInfosListener>>
+            windowInfosListeners;
+
+    {
+        std::scoped_lock lock(mListenersMutex);
+        for (auto listener : mWindowInfosListeners) {
+            windowInfosListeners.insert(listener);
+        }
+    }
+
+    for (auto listener : windowInfosListeners) {
+        listener->onWindowInfosChanged(windowInfos);
+    }
+
+    return binder::Status::ok();
+}
+
+void WindowInfosListenerReporter::reconnect(const sp<ISurfaceComposer>& composerService) {
+    std::scoped_lock lock(mListenersMutex);
+    if (!mWindowInfosListeners.empty()) {
+        composerService->addWindowInfosListener(this);
+    }
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/gui/android/gui/IWindowInfosListener.aidl b/libs/gui/android/gui/IWindowInfosListener.aidl
new file mode 100644
index 0000000..500d928
--- /dev/null
+++ b/libs/gui/android/gui/IWindowInfosListener.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package android.gui;
+
+import android.gui.WindowInfo;
+
+/** @hide */
+oneway interface IWindowInfosListener
+{
+    void onWindowInfosChanged(in WindowInfo[] windowInfos);
+}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 71b80d3..ad7bcb7 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -22,6 +22,7 @@
 #include <android/gui/IScreenCaptureListener.h>
 #include <android/gui/ITransactionTraceListener.h>
 #include <android/gui/ITunnelModeEnabledListener.h>
+#include <android/gui/IWindowInfosListener.h>
 #include <binder/IBinder.h>
 #include <binder/IInterface.h>
 #include <ftl/Flags.h>
@@ -552,6 +553,11 @@
      * in MIN_UNDEQUEUED_BUFFERS.
      */
     virtual status_t getMaxAcquiredBufferCount(int* buffers) const = 0;
+
+    virtual status_t addWindowInfosListener(
+            const sp<gui::IWindowInfosListener>& windowInfosListener) const = 0;
+    virtual status_t removeWindowInfosListener(
+            const sp<gui::IWindowInfosListener>& windowInfosListener) const = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -624,6 +630,8 @@
         ON_PULL_ATOM,
         ADD_TUNNEL_MODE_ENABLED_LISTENER,
         REMOVE_TUNNEL_MODE_ENABLED_LISTENER,
+        ADD_WINDOW_INFOS_LISTENER,
+        REMOVE_WINDOW_INFOS_LISTENER,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index ff97fe4..e718f3d 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -42,6 +42,7 @@
 #include <gui/ITransactionCompletedListener.h>
 #include <gui/LayerState.h>
 #include <gui/SurfaceControl.h>
+#include <gui/WindowInfosListenerReporter.h>
 #include <math/vec3.h>
 
 namespace android {
@@ -619,6 +620,9 @@
     static status_t removeTunnelModeEnabledListener(
             const sp<gui::ITunnelModeEnabledListener>& listener);
 
+    status_t addWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener);
+    status_t removeWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener);
+
 private:
     virtual void onFirstRef();
 
diff --git a/libs/gui/include/gui/WindowInfosListener.h b/libs/gui/include/gui/WindowInfosListener.h
new file mode 100644
index 0000000..8a70b9b
--- /dev/null
+++ b/libs/gui/include/gui/WindowInfosListener.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#pragma once
+
+#include <gui/WindowInfo.h>
+#include <utils/RefBase.h>
+
+namespace android::gui {
+
+class WindowInfosListener : public virtual RefBase {
+public:
+    virtual void onWindowInfosChanged(const std::vector<WindowInfo>& /*windowInfos*/) = 0;
+};
+} // namespace android::gui
\ No newline at end of file
diff --git a/libs/gui/include/gui/WindowInfosListenerReporter.h b/libs/gui/include/gui/WindowInfosListenerReporter.h
new file mode 100644
index 0000000..3e346de
--- /dev/null
+++ b/libs/gui/include/gui/WindowInfosListenerReporter.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/gui/BnWindowInfosListener.h>
+#include <binder/IBinder.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/WindowInfosListener.h>
+#include <utils/Mutex.h>
+#include <unordered_set>
+
+namespace android {
+class ISurfaceComposer;
+
+class WindowInfosListenerReporter : public gui::BnWindowInfosListener {
+public:
+    static sp<WindowInfosListenerReporter> getInstance();
+
+    binder::Status onWindowInfosChanged(const std::vector<gui::WindowInfo>& windowInfos) override;
+
+    status_t addWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener,
+                                    const sp<ISurfaceComposer>&);
+    status_t removeWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener,
+                                       const sp<ISurfaceComposer>&);
+    void reconnect(const sp<ISurfaceComposer>&);
+
+private:
+    std::mutex mListenersMutex;
+    std::unordered_set<sp<gui::WindowInfosListener>,
+                       ISurfaceComposer::SpHash<gui::WindowInfosListener>>
+            mWindowInfosListeners GUARDED_BY(mListenersMutex);
+};
+} // namespace android
\ No newline at end of file
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 59b0c04..a02970c 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -904,6 +904,16 @@
 
     status_t getMaxAcquiredBufferCount(int* /*buffers*/) const override { return NO_ERROR; }
 
+    status_t addWindowInfosListener(
+            const sp<gui::IWindowInfosListener>& /*windowInfosListener*/) const override {
+        return NO_ERROR;
+    }
+
+    status_t removeWindowInfosListener(
+            const sp<gui::IWindowInfosListener>& /*windowInfosListener*/) const override {
+        return NO_ERROR;
+    }
+
 protected:
     IBinder* onAsBinder() override { return nullptr; }