1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "WindowInfosListenerInvoker.h"
18 #include <gui/ISurfaceComposer.h>
19 #include <unordered_set>
20 #include "SurfaceFlinger.h"
21 
22 namespace android {
23 
24 using gui::IWindowInfosListener;
25 using gui::WindowInfo;
26 
27 struct WindowInfosReportedListener : gui::BnWindowInfosReportedListener {
WindowInfosReportedListenerandroid::WindowInfosReportedListener28     explicit WindowInfosReportedListener(std::function<void()> listenerCb)
29           : mListenerCb(listenerCb) {}
30 
onWindowInfosReportedandroid::WindowInfosReportedListener31     binder::Status onWindowInfosReported() override {
32         if (mListenerCb != nullptr) {
33             mListenerCb();
34         }
35         return binder::Status::ok();
36     }
37 
38     std::function<void()> mListenerCb;
39 };
40 
WindowInfosListenerInvoker(const sp<SurfaceFlinger> & sf)41 WindowInfosListenerInvoker::WindowInfosListenerInvoker(const sp<SurfaceFlinger>& sf) : mSf(sf) {
42     mWindowInfosReportedListener =
43             new WindowInfosReportedListener([&]() { windowInfosReported(); });
44 }
45 
addWindowInfosListener(const sp<IWindowInfosListener> & windowInfosListener)46 void WindowInfosListenerInvoker::addWindowInfosListener(
47         const sp<IWindowInfosListener>& windowInfosListener) {
48     sp<IBinder> asBinder = IInterface::asBinder(windowInfosListener);
49 
50     asBinder->linkToDeath(this);
51     std::scoped_lock lock(mListenersMutex);
52     mWindowInfosListeners.emplace(asBinder, windowInfosListener);
53 }
54 
removeWindowInfosListener(const sp<IWindowInfosListener> & windowInfosListener)55 void WindowInfosListenerInvoker::removeWindowInfosListener(
56         const sp<IWindowInfosListener>& windowInfosListener) {
57     sp<IBinder> asBinder = IInterface::asBinder(windowInfosListener);
58 
59     std::scoped_lock lock(mListenersMutex);
60     asBinder->unlinkToDeath(this);
61     mWindowInfosListeners.erase(asBinder);
62 }
63 
binderDied(const wp<IBinder> & who)64 void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) {
65     std::scoped_lock lock(mListenersMutex);
66     mWindowInfosListeners.erase(who);
67 }
68 
windowInfosChanged(const std::vector<WindowInfo> & windowInfos,bool shouldSync)69 void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos,
70                                                     bool shouldSync) {
71     std::unordered_set<sp<IWindowInfosListener>, ISurfaceComposer::SpHash<IWindowInfosListener>>
72             windowInfosListeners;
73 
74     {
75         std::scoped_lock lock(mListenersMutex);
76         for (const auto& [_, listener] : mWindowInfosListeners) {
77             windowInfosListeners.insert(listener);
78         }
79     }
80 
81     mCallbacksPending = windowInfosListeners.size();
82 
83     for (const auto& listener : windowInfosListeners) {
84         listener->onWindowInfosChanged(windowInfos,
85                                        shouldSync ? mWindowInfosReportedListener : nullptr);
86     }
87 }
88 
windowInfosReported()89 void WindowInfosListenerInvoker::windowInfosReported() {
90     mCallbacksPending--;
91     if (mCallbacksPending == 0) {
92         mSf->windowInfosReported();
93     }
94 }
95 
96 } // namespace android