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 <android/gui/ISurfaceComposer.h>
18 #include <gui/AidlStatusUtil.h>
19 #include <gui/WindowInfosListenerReporter.h>
20 #include "gui/WindowInfosUpdate.h"
21 
22 namespace android {
23 
24 using gui::DisplayInfo;
25 using gui::WindowInfo;
26 using gui::WindowInfosListener;
27 using gui::aidl_utils::statusTFromBinderStatus;
28 
getInstance()29 sp<WindowInfosListenerReporter> WindowInfosListenerReporter::getInstance() {
30     static sp<WindowInfosListenerReporter> sInstance = new WindowInfosListenerReporter;
31     return sInstance;
32 }
33 
addWindowInfosListener(const sp<WindowInfosListener> & windowInfosListener,const sp<gui::ISurfaceComposer> & surfaceComposer,std::pair<std::vector<gui::WindowInfo>,std::vector<gui::DisplayInfo>> * outInitialInfo)34 status_t WindowInfosListenerReporter::addWindowInfosListener(
35         const sp<WindowInfosListener>& windowInfosListener,
36         const sp<gui::ISurfaceComposer>& surfaceComposer,
37         std::pair<std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>>* outInitialInfo) {
38     status_t status = OK;
39     {
40         std::scoped_lock lock(mListenersMutex);
41         if (mWindowInfosListeners.empty()) {
42             gui::WindowInfosListenerInfo listenerInfo;
43             binder::Status s = surfaceComposer->addWindowInfosListener(this, &listenerInfo);
44             status = statusTFromBinderStatus(s);
45             if (status == OK) {
46                 mWindowInfosPublisher = std::move(listenerInfo.windowInfosPublisher);
47                 mListenerId = listenerInfo.listenerId;
48             }
49         }
50 
51         if (status == OK) {
52             mWindowInfosListeners.insert(windowInfosListener);
53         }
54 
55         if (outInitialInfo != nullptr) {
56             outInitialInfo->first = mLastWindowInfos;
57             outInitialInfo->second = mLastDisplayInfos;
58         }
59     }
60 
61     return status;
62 }
63 
removeWindowInfosListener(const sp<WindowInfosListener> & windowInfosListener,const sp<gui::ISurfaceComposer> & surfaceComposer)64 status_t WindowInfosListenerReporter::removeWindowInfosListener(
65         const sp<WindowInfosListener>& windowInfosListener,
66         const sp<gui::ISurfaceComposer>& surfaceComposer) {
67     status_t status = OK;
68     {
69         std::scoped_lock lock(mListenersMutex);
70         if (mWindowInfosListeners.find(windowInfosListener) == mWindowInfosListeners.end()) {
71             return status;
72         }
73 
74         if (mWindowInfosListeners.size() == 1) {
75             binder::Status s = surfaceComposer->removeWindowInfosListener(this);
76             status = statusTFromBinderStatus(s);
77             // Clear the last stored state since we're disabling updates and don't want to hold
78             // stale values
79             mLastWindowInfos.clear();
80             mLastDisplayInfos.clear();
81         }
82 
83         if (status == OK) {
84             mWindowInfosListeners.erase(windowInfosListener);
85         }
86     }
87 
88     return status;
89 }
90 
onWindowInfosChanged(const gui::WindowInfosUpdate & update)91 binder::Status WindowInfosListenerReporter::onWindowInfosChanged(
92         const gui::WindowInfosUpdate& update) {
93     std::unordered_set<sp<WindowInfosListener>, gui::SpHash<WindowInfosListener>>
94             windowInfosListeners;
95 
96     {
97         std::scoped_lock lock(mListenersMutex);
98         for (auto listener : mWindowInfosListeners) {
99             windowInfosListeners.insert(listener);
100         }
101 
102         mLastWindowInfos = update.windowInfos;
103         mLastDisplayInfos = update.displayInfos;
104     }
105 
106     for (auto listener : windowInfosListeners) {
107         listener->onWindowInfosChanged(update);
108     }
109 
110     mWindowInfosPublisher->ackWindowInfosReceived(update.vsyncId, mListenerId);
111 
112     return binder::Status::ok();
113 }
114 
reconnect(const sp<gui::ISurfaceComposer> & composerService)115 void WindowInfosListenerReporter::reconnect(const sp<gui::ISurfaceComposer>& composerService) {
116     std::scoped_lock lock(mListenersMutex);
117     if (!mWindowInfosListeners.empty()) {
118         gui::WindowInfosListenerInfo listenerInfo;
119         composerService->addWindowInfosListener(this, &listenerInfo);
120         mWindowInfosPublisher = std::move(listenerInfo.windowInfosPublisher);
121         mListenerId = listenerInfo.listenerId;
122     }
123 }
124 
125 } // namespace android
126