• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/BnWindowInfosPublisher.h>
18 #include <android/gui/IWindowInfosPublisher.h>
19 #include <android/gui/WindowInfosListenerInfo.h>
20 #include <gui/ISurfaceComposer.h>
21 #include <gui/TraceUtils.h>
22 #include <gui/WindowInfosUpdate.h>
23 #include <scheduler/Time.h>
24 
25 #include "BackgroundExecutor.h"
26 #include "WindowInfosListenerInvoker.h"
27 
28 #undef ATRACE_TAG
29 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
30 
31 namespace android {
32 
33 using gui::DisplayInfo;
34 using gui::IWindowInfosListener;
35 using gui::WindowInfo;
36 
addWindowInfosListener(sp<IWindowInfosListener> listener,gui::WindowInfosListenerInfo * outInfo)37 void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener,
38                                                         gui::WindowInfosListenerInfo* outInfo) {
39     int64_t listenerId = mNextListenerId++;
40     outInfo->listenerId = listenerId;
41     outInfo->windowInfosPublisher = sp<gui::IWindowInfosPublisher>::fromExisting(this);
42 
43     BackgroundExecutor::getInstance().sendCallbacks(
44             {[this, listener = std::move(listener), listenerId]() {
45                 ATRACE_NAME("WindowInfosListenerInvoker::addWindowInfosListener");
46                 sp<IBinder> asBinder = IInterface::asBinder(listener);
47                 asBinder->linkToDeath(sp<DeathRecipient>::fromExisting(this));
48                 mWindowInfosListeners.try_emplace(asBinder,
49                                                   std::make_pair(listenerId, std::move(listener)));
50             }});
51 }
52 
removeWindowInfosListener(const sp<IWindowInfosListener> & listener)53 void WindowInfosListenerInvoker::removeWindowInfosListener(
54         const sp<IWindowInfosListener>& listener) {
55     BackgroundExecutor::getInstance().sendCallbacks({[this, listener]() {
56         ATRACE_NAME("WindowInfosListenerInvoker::removeWindowInfosListener");
57         sp<IBinder> asBinder = IInterface::asBinder(listener);
58         asBinder->unlinkToDeath(sp<DeathRecipient>::fromExisting(this));
59         mWindowInfosListeners.erase(asBinder);
60     }});
61 }
62 
binderDied(const wp<IBinder> & who)63 void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) {
64     BackgroundExecutor::getInstance().sendCallbacks({[this, who]() {
65         ATRACE_NAME("WindowInfosListenerInvoker::binderDied");
66         auto it = mWindowInfosListeners.find(who);
67         int64_t listenerId = it->second.first;
68         mWindowInfosListeners.erase(who);
69 
70         std::vector<int64_t> vsyncIds;
71         for (auto& [vsyncId, state] : mUnackedState) {
72             if (std::find(state.unackedListenerIds.begin(), state.unackedListenerIds.end(),
73                           listenerId) != state.unackedListenerIds.end()) {
74                 vsyncIds.push_back(vsyncId);
75             }
76         }
77 
78         for (int64_t vsyncId : vsyncIds) {
79             ackWindowInfosReceived(vsyncId, listenerId);
80         }
81     }});
82 }
83 
windowInfosChanged(gui::WindowInfosUpdate update,WindowInfosReportedListenerSet reportedListeners,bool forceImmediateCall)84 void WindowInfosListenerInvoker::windowInfosChanged(
85         gui::WindowInfosUpdate update, WindowInfosReportedListenerSet reportedListeners,
86         bool forceImmediateCall) {
87     if (!mDelayInfo) {
88         mDelayInfo = DelayInfo{
89                 .vsyncId = update.vsyncId,
90                 .frameTime = update.timestamp,
91         };
92     }
93 
94     // If there are unacked messages and this isn't a forced call, then return immediately.
95     // If a forced window infos change doesn't happen first, the update will be sent after
96     // the WindowInfosReportedListeners are called. If a forced window infos change happens or
97     // if there are subsequent delayed messages before this update is sent, then this message
98     // will be dropped and the listeners will only be called with the latest info. This is done
99     // to reduce the amount of binder memory used.
100     if (!mUnackedState.empty() && !forceImmediateCall) {
101         mDelayedUpdate = std::move(update);
102         mReportedListeners.merge(reportedListeners);
103         return;
104     }
105 
106     if (mDelayedUpdate) {
107         mDelayedUpdate.reset();
108     }
109 
110     if (CC_UNLIKELY(mWindowInfosListeners.empty())) {
111         mReportedListeners.merge(reportedListeners);
112         mDelayInfo.reset();
113         return;
114     }
115 
116     reportedListeners.merge(mReportedListeners);
117     mReportedListeners.clear();
118 
119     // Update mUnackedState to include the message we're about to send
120     auto [it, _] = mUnackedState.try_emplace(update.vsyncId,
121                                              UnackedState{.reportedListeners =
122                                                                   std::move(reportedListeners)});
123     auto& unackedState = it->second;
124     for (auto& pair : mWindowInfosListeners) {
125         int64_t listenerId = pair.second.first;
126         unackedState.unackedListenerIds.push_back(listenerId);
127     }
128 
129     mDelayInfo.reset();
130     updateMaxSendDelay();
131 
132     // Call the listeners
133     for (auto& pair : mWindowInfosListeners) {
134         auto& [listenerId, listener] = pair.second;
135         auto status = listener->onWindowInfosChanged(update);
136         if (!status.isOk()) {
137             ackWindowInfosReceived(update.vsyncId, listenerId);
138         }
139     }
140 }
141 
getDebugInfo()142 WindowInfosListenerInvoker::DebugInfo WindowInfosListenerInvoker::getDebugInfo() {
143     DebugInfo result;
144     BackgroundExecutor::getInstance().sendCallbacks({[&, this]() {
145         ATRACE_NAME("WindowInfosListenerInvoker::getDebugInfo");
146         updateMaxSendDelay();
147         result = mDebugInfo;
148         result.pendingMessageCount = mUnackedState.size();
149     }});
150     BackgroundExecutor::getInstance().flushQueue();
151     return result;
152 }
153 
updateMaxSendDelay()154 void WindowInfosListenerInvoker::updateMaxSendDelay() {
155     if (!mDelayInfo) {
156         return;
157     }
158     nsecs_t delay = TimePoint::now().ns() - mDelayInfo->frameTime;
159     if (delay > mDebugInfo.maxSendDelayDuration) {
160         mDebugInfo.maxSendDelayDuration = delay;
161         mDebugInfo.maxSendDelayVsyncId = VsyncId{mDelayInfo->vsyncId};
162     }
163 }
164 
ackWindowInfosReceived(int64_t vsyncId,int64_t listenerId)165 binder::Status WindowInfosListenerInvoker::ackWindowInfosReceived(int64_t vsyncId,
166                                                                   int64_t listenerId) {
167     BackgroundExecutor::getInstance().sendCallbacks({[this, vsyncId, listenerId]() {
168         ATRACE_NAME("WindowInfosListenerInvoker::ackWindowInfosReceived");
169         auto it = mUnackedState.find(vsyncId);
170         if (it == mUnackedState.end()) {
171             return;
172         }
173 
174         auto& state = it->second;
175         state.unackedListenerIds.unstable_erase(std::find(state.unackedListenerIds.begin(),
176                                                           state.unackedListenerIds.end(),
177                                                           listenerId));
178         if (!state.unackedListenerIds.empty()) {
179             return;
180         }
181 
182         WindowInfosReportedListenerSet reportedListeners{std::move(state.reportedListeners)};
183         mUnackedState.erase(vsyncId);
184 
185         for (const auto& reportedListener : reportedListeners) {
186             sp<IBinder> asBinder = IInterface::asBinder(reportedListener);
187             if (asBinder->isBinderAlive()) {
188                 reportedListener->onWindowInfosReported();
189             }
190         }
191 
192         if (!mDelayedUpdate || !mUnackedState.empty()) {
193             return;
194         }
195         gui::WindowInfosUpdate update{std::move(*mDelayedUpdate)};
196         mDelayedUpdate.reset();
197         windowInfosChanged(std::move(update), {}, false);
198     }});
199     return binder::Status::ok();
200 }
201 
202 } // namespace android
203