• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 //#define LOG_NDEBUG 0
18 #undef LOG_TAG
19 #define LOG_TAG "TransactionCompletedThread"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 
22 #include "TransactionCompletedThread.h"
23 
24 #include <cinttypes>
25 
26 #include <binder/IInterface.h>
27 #include <gui/ITransactionCompletedListener.h>
28 #include <utils/RefBase.h>
29 
30 namespace android {
31 
32 // Returns 0 if they are equal
33 //         <0 if the first id that doesn't match is lower in c2 or all ids match but c2 is shorter
34 //         >0 if the first id that doesn't match is greater in c2 or all ids match but c2 is longer
35 //
36 // See CallbackIdsHash for a explaniation of why this works
compareCallbackIds(const std::vector<CallbackId> & c1,const std::vector<CallbackId> & c2)37 static int compareCallbackIds(const std::vector<CallbackId>& c1,
38                               const std::vector<CallbackId>& c2) {
39     if (c1.empty()) {
40         return !c2.empty();
41     }
42     return c1.front() - c2.front();
43 }
44 
~TransactionCompletedThread()45 TransactionCompletedThread::~TransactionCompletedThread() {
46     std::lock_guard lockThread(mThreadMutex);
47 
48     {
49         std::lock_guard lock(mMutex);
50         mKeepRunning = false;
51         mConditionVariable.notify_all();
52     }
53 
54     if (mThread.joinable()) {
55         mThread.join();
56     }
57 
58     {
59         std::lock_guard lock(mMutex);
60         for (const auto& [listener, transactionStats] : mCompletedTransactions) {
61             IInterface::asBinder(listener)->unlinkToDeath(mDeathRecipient);
62         }
63     }
64 }
65 
run()66 void TransactionCompletedThread::run() {
67     std::lock_guard lock(mMutex);
68     if (mRunning || !mKeepRunning) {
69         return;
70     }
71     mDeathRecipient = new ThreadDeathRecipient();
72     mRunning = true;
73 
74     std::lock_guard lockThread(mThreadMutex);
75     mThread = std::thread(&TransactionCompletedThread::threadMain, this);
76 }
77 
addCallback(const sp<ITransactionCompletedListener> & listener,const std::vector<CallbackId> & callbackIds)78 status_t TransactionCompletedThread::addCallback(const sp<ITransactionCompletedListener>& listener,
79                                                  const std::vector<CallbackId>& callbackIds) {
80     std::lock_guard lock(mMutex);
81     if (!mRunning) {
82         ALOGE("cannot add callback because the callback thread isn't running");
83         return BAD_VALUE;
84     }
85 
86     if (mCompletedTransactions.count(listener) == 0) {
87         status_t err = IInterface::asBinder(listener)->linkToDeath(mDeathRecipient);
88         if (err != NO_ERROR) {
89             ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
90             return err;
91         }
92     }
93 
94     auto& transactionStatsDeque = mCompletedTransactions[listener];
95     transactionStatsDeque.emplace_back(callbackIds);
96     return NO_ERROR;
97 }
98 
registerPendingCallbackHandle(const sp<CallbackHandle> & handle)99 status_t TransactionCompletedThread::registerPendingCallbackHandle(
100         const sp<CallbackHandle>& handle) {
101     std::lock_guard lock(mMutex);
102     if (!mRunning) {
103         ALOGE("cannot register callback handle because the callback thread isn't running");
104         return BAD_VALUE;
105     }
106 
107     // If we can't find the transaction stats something has gone wrong. The client should call
108     // addCallback before trying to register a pending callback handle.
109     TransactionStats* transactionStats;
110     status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
111     if (err != NO_ERROR) {
112         ALOGE("cannot find transaction stats");
113         return err;
114     }
115 
116     mPendingTransactions[handle->listener][handle->callbackIds]++;
117     return NO_ERROR;
118 }
119 
addPresentedCallbackHandles(const std::deque<sp<CallbackHandle>> & handles)120 status_t TransactionCompletedThread::addPresentedCallbackHandles(
121         const std::deque<sp<CallbackHandle>>& handles) {
122     std::lock_guard lock(mMutex);
123     if (!mRunning) {
124         ALOGE("cannot add presented callback handle because the callback thread isn't running");
125         return BAD_VALUE;
126     }
127 
128     for (const auto& handle : handles) {
129         auto listener = mPendingTransactions.find(handle->listener);
130         if (listener != mPendingTransactions.end()) {
131             auto& pendingCallbacks = listener->second;
132             auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
133 
134             if (pendingCallback != pendingCallbacks.end()) {
135                 auto& pendingCount = pendingCallback->second;
136 
137                 // Decrease the pending count for this listener
138                 if (--pendingCount == 0) {
139                     pendingCallbacks.erase(pendingCallback);
140                 }
141             } else {
142                 ALOGW("there are more latched callbacks than there were registered callbacks");
143             }
144             if (listener->second.size() == 0) {
145                 mPendingTransactions.erase(listener);
146             }
147         } else {
148             ALOGW("cannot find listener in mPendingTransactions");
149         }
150 
151         status_t err = addCallbackHandle(handle);
152         if (err != NO_ERROR) {
153             ALOGE("could not add callback handle");
154             return err;
155         }
156     }
157 
158     return NO_ERROR;
159 }
160 
addUnpresentedCallbackHandle(const sp<CallbackHandle> & handle)161 status_t TransactionCompletedThread::addUnpresentedCallbackHandle(
162         const sp<CallbackHandle>& handle) {
163     std::lock_guard lock(mMutex);
164     if (!mRunning) {
165         ALOGE("cannot add unpresented callback handle because the callback thread isn't running");
166         return BAD_VALUE;
167     }
168 
169     return addCallbackHandle(handle);
170 }
171 
findTransactionStats(const sp<ITransactionCompletedListener> & listener,const std::vector<CallbackId> & callbackIds,TransactionStats ** outTransactionStats)172 status_t TransactionCompletedThread::findTransactionStats(
173         const sp<ITransactionCompletedListener>& listener,
174         const std::vector<CallbackId>& callbackIds, TransactionStats** outTransactionStats) {
175     auto& transactionStatsDeque = mCompletedTransactions[listener];
176 
177     // Search back to front because the most recent transactions are at the back of the deque
178     auto itr = transactionStatsDeque.rbegin();
179     for (; itr != transactionStatsDeque.rend(); itr++) {
180         if (compareCallbackIds(itr->callbackIds, callbackIds) == 0) {
181             *outTransactionStats = &(*itr);
182             return NO_ERROR;
183         }
184     }
185 
186     ALOGE("could not find transaction stats");
187     return BAD_VALUE;
188 }
189 
addCallbackHandle(const sp<CallbackHandle> & handle)190 status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
191     // If we can't find the transaction stats something has gone wrong. The client should call
192     // addCallback before trying to add a presnted callback handle.
193     TransactionStats* transactionStats;
194     status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
195     if (err != NO_ERROR) {
196         return err;
197     }
198 
199     transactionStats->latchTime = handle->latchTime;
200     // If the layer has already been destroyed, don't add the SurfaceControl to the callback.
201     // The client side keeps a sp<> to the SurfaceControl so if the SurfaceControl has been
202     // destroyed the client side is dead and there won't be anyone to send the callback to.
203     sp<IBinder> surfaceControl = handle->surfaceControl.promote();
204     if (surfaceControl) {
205         transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
206                                                     handle->previousReleaseFence);
207     }
208     return NO_ERROR;
209 }
210 
addPresentFence(const sp<Fence> & presentFence)211 void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
212     std::lock_guard<std::mutex> lock(mMutex);
213     mPresentFence = presentFence;
214 }
215 
sendCallbacks()216 void TransactionCompletedThread::sendCallbacks() {
217     std::lock_guard lock(mMutex);
218     if (mRunning) {
219         mConditionVariable.notify_all();
220     }
221 }
222 
threadMain()223 void TransactionCompletedThread::threadMain() {
224     std::lock_guard lock(mMutex);
225 
226     while (mKeepRunning) {
227         mConditionVariable.wait(mMutex);
228         std::vector<ListenerStats> completedListenerStats;
229 
230         // For each listener
231         auto completedTransactionsItr = mCompletedTransactions.begin();
232         while (completedTransactionsItr != mCompletedTransactions.end()) {
233             auto& [listener, transactionStatsDeque] = *completedTransactionsItr;
234             ListenerStats listenerStats;
235             listenerStats.listener = listener;
236 
237             // For each transaction
238             auto transactionStatsItr = transactionStatsDeque.begin();
239             while (transactionStatsItr != transactionStatsDeque.end()) {
240                 auto& transactionStats = *transactionStatsItr;
241 
242                 // If we are still waiting on the callback handles for this transaction, stop
243                 // here because all transaction callbacks for the same listener must come in order
244                 auto pendingTransactions = mPendingTransactions.find(listener);
245                 if (pendingTransactions != mPendingTransactions.end() &&
246                     pendingTransactions->second.count(transactionStats.callbackIds) != 0) {
247                     break;
248                 }
249 
250                 // If the transaction has been latched
251                 if (transactionStats.latchTime >= 0) {
252                     if (!mPresentFence) {
253                         break;
254                     }
255                     transactionStats.presentFence = mPresentFence;
256                 }
257 
258                 // Remove the transaction from completed to the callback
259                 listenerStats.transactionStats.push_back(std::move(transactionStats));
260                 transactionStatsItr = transactionStatsDeque.erase(transactionStatsItr);
261             }
262             // If the listener has completed transactions
263             if (!listenerStats.transactionStats.empty()) {
264                 // If the listener is still alive
265                 if (IInterface::asBinder(listener)->isBinderAlive()) {
266                     // Send callback
267                     listenerStats.listener->onTransactionCompleted(listenerStats);
268                     IInterface::asBinder(listener)->unlinkToDeath(mDeathRecipient);
269                 }
270                 completedTransactionsItr = mCompletedTransactions.erase(completedTransactionsItr);
271             } else {
272                 completedTransactionsItr++;
273             }
274 
275             completedListenerStats.push_back(std::move(listenerStats));
276         }
277 
278         if (mPresentFence) {
279             mPresentFence.clear();
280         }
281 
282         // If everyone else has dropped their reference to a layer and its listener is dead,
283         // we are about to cause the layer to be deleted. If this happens at the wrong time and
284         // we are holding mMutex, we will cause a deadlock.
285         //
286         // The deadlock happens because this thread is holding on to mMutex and when we delete
287         // the layer, it grabs SF's mStateLock. A different SF binder thread grabs mStateLock,
288         // then call's TransactionCompletedThread::run() which tries to grab mMutex.
289         //
290         // To avoid this deadlock, we need to unlock mMutex when dropping our last reference to
291         // to the layer.
292         mMutex.unlock();
293         completedListenerStats.clear();
294         mMutex.lock();
295     }
296 }
297 
298 // -----------------------------------------------------------------------
299 
CallbackHandle(const sp<ITransactionCompletedListener> & transactionListener,const std::vector<CallbackId> & ids,const sp<IBinder> & sc)300 CallbackHandle::CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
301                                const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
302       : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
303 
304 } // namespace android
305