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 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 
21 //#define LOG_NDEBUG 0
22 #undef LOG_TAG
23 #define LOG_TAG "TransactionCompletedThread"
24 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
25 
26 #include "TransactionCompletedThread.h"
27 
28 #include <cinttypes>
29 
30 #include <binder/IInterface.h>
31 #include <utils/RefBase.h>
32 
33 namespace android {
34 
35 // Returns 0 if they are equal
36 //         <0 if the first id that doesn't match is lower in c2 or all ids match but c2 is shorter
37 //         >0 if the first id that doesn't match is greater in c2 or all ids match but c2 is longer
38 //
39 // See CallbackIdsHash for a explaniation of why this works
compareCallbackIds(const std::vector<CallbackId> & c1,const std::vector<CallbackId> & c2)40 static int compareCallbackIds(const std::vector<CallbackId>& c1,
41                               const std::vector<CallbackId>& c2) {
42     if (c1.empty()) {
43         return !c2.empty();
44     }
45     return c1.front() - c2.front();
46 }
47 
~TransactionCompletedThread()48 TransactionCompletedThread::~TransactionCompletedThread() {
49     std::lock_guard lockThread(mThreadMutex);
50 
51     {
52         std::lock_guard lock(mMutex);
53         mKeepRunning = false;
54         mConditionVariable.notify_all();
55     }
56 
57     if (mThread.joinable()) {
58         mThread.join();
59     }
60 
61     {
62         std::lock_guard lock(mMutex);
63         for (const auto& [listener, transactionStats] : mCompletedTransactions) {
64             listener->unlinkToDeath(mDeathRecipient);
65         }
66     }
67 }
68 
run()69 void TransactionCompletedThread::run() {
70     std::lock_guard lock(mMutex);
71     if (mRunning || !mKeepRunning) {
72         return;
73     }
74     mDeathRecipient = new ThreadDeathRecipient();
75     mRunning = true;
76 
77     std::lock_guard lockThread(mThreadMutex);
78     mThread = std::thread(&TransactionCompletedThread::threadMain, this);
79 }
80 
startRegistration(const ListenerCallbacks & listenerCallbacks)81 status_t TransactionCompletedThread::startRegistration(const ListenerCallbacks& listenerCallbacks) {
82     // begin running if not already running
83     run();
84     std::lock_guard lock(mMutex);
85     if (!mRunning) {
86         ALOGE("cannot add callback because the callback thread isn't running");
87         return BAD_VALUE;
88     }
89 
90     auto [itr, inserted] = mRegisteringTransactions.insert(listenerCallbacks);
91     auto& [listener, callbackIds] = listenerCallbacks;
92 
93     if (inserted) {
94         if (mCompletedTransactions.count(listener) == 0) {
95             status_t err = listener->linkToDeath(mDeathRecipient);
96             if (err != NO_ERROR) {
97                 ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
98                 return err;
99             }
100         }
101         auto& transactionStatsDeque = mCompletedTransactions[listener];
102         transactionStatsDeque.emplace_back(callbackIds);
103     }
104 
105     return NO_ERROR;
106 }
107 
endRegistration(const ListenerCallbacks & listenerCallbacks)108 status_t TransactionCompletedThread::endRegistration(const ListenerCallbacks& listenerCallbacks) {
109     std::lock_guard lock(mMutex);
110     if (!mRunning) {
111         ALOGE("cannot add callback because the callback thread isn't running");
112         return BAD_VALUE;
113     }
114 
115     auto itr = mRegisteringTransactions.find(listenerCallbacks);
116     if (itr == mRegisteringTransactions.end()) {
117         ALOGE("cannot end a registration that does not exist");
118         return BAD_VALUE;
119     }
120 
121     mRegisteringTransactions.erase(itr);
122 
123     return NO_ERROR;
124 }
125 
isRegisteringTransaction(const sp<IBinder> & transactionListener,const std::vector<CallbackId> & callbackIds)126 bool TransactionCompletedThread::isRegisteringTransaction(
127         const sp<IBinder>& transactionListener, const std::vector<CallbackId>& callbackIds) {
128     ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
129 
130     auto itr = mRegisteringTransactions.find(listenerCallbacks);
131     return itr != mRegisteringTransactions.end();
132 }
133 
registerPendingCallbackHandle(const sp<CallbackHandle> & handle)134 status_t TransactionCompletedThread::registerPendingCallbackHandle(
135         const sp<CallbackHandle>& handle) {
136     std::lock_guard lock(mMutex);
137     if (!mRunning) {
138         ALOGE("cannot register callback handle because the callback thread isn't running");
139         return BAD_VALUE;
140     }
141 
142     // If we can't find the transaction stats something has gone wrong. The client should call
143     // startRegistration before trying to register a pending callback handle.
144     TransactionStats* transactionStats;
145     status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
146     if (err != NO_ERROR) {
147         ALOGE("cannot find transaction stats");
148         return err;
149     }
150 
151     mPendingTransactions[handle->listener][handle->callbackIds]++;
152     return NO_ERROR;
153 }
154 
finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>> & handles)155 status_t TransactionCompletedThread::finalizePendingCallbackHandles(
156         const std::deque<sp<CallbackHandle>>& handles) {
157     if (handles.empty()) {
158         return NO_ERROR;
159     }
160     std::lock_guard lock(mMutex);
161     if (!mRunning) {
162         ALOGE("cannot add presented callback handle because the callback thread isn't running");
163         return BAD_VALUE;
164     }
165 
166     for (const auto& handle : handles) {
167         auto listener = mPendingTransactions.find(handle->listener);
168         if (listener != mPendingTransactions.end()) {
169             auto& pendingCallbacks = listener->second;
170             auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
171 
172             if (pendingCallback != pendingCallbacks.end()) {
173                 auto& pendingCount = pendingCallback->second;
174 
175                 // Decrease the pending count for this listener
176                 if (--pendingCount == 0) {
177                     pendingCallbacks.erase(pendingCallback);
178                 }
179             } else {
180                 ALOGW("there are more latched callbacks than there were registered callbacks");
181             }
182             if (listener->second.size() == 0) {
183                 mPendingTransactions.erase(listener);
184             }
185         } else {
186             ALOGW("cannot find listener in mPendingTransactions");
187         }
188 
189         status_t err = addCallbackHandle(handle);
190         if (err != NO_ERROR) {
191             ALOGE("could not add callback handle");
192             return err;
193         }
194     }
195 
196     return NO_ERROR;
197 }
198 
registerUnpresentedCallbackHandle(const sp<CallbackHandle> & handle)199 status_t TransactionCompletedThread::registerUnpresentedCallbackHandle(
200         const sp<CallbackHandle>& handle) {
201     std::lock_guard lock(mMutex);
202     if (!mRunning) {
203         ALOGE("cannot add unpresented callback handle because the callback thread isn't running");
204         return BAD_VALUE;
205     }
206 
207     return addCallbackHandle(handle);
208 }
209 
findTransactionStats(const sp<IBinder> & listener,const std::vector<CallbackId> & callbackIds,TransactionStats ** outTransactionStats)210 status_t TransactionCompletedThread::findTransactionStats(
211         const sp<IBinder>& listener, const std::vector<CallbackId>& callbackIds,
212         TransactionStats** outTransactionStats) {
213     auto& transactionStatsDeque = mCompletedTransactions[listener];
214 
215     // Search back to front because the most recent transactions are at the back of the deque
216     auto itr = transactionStatsDeque.rbegin();
217     for (; itr != transactionStatsDeque.rend(); itr++) {
218         if (compareCallbackIds(itr->callbackIds, callbackIds) == 0) {
219             *outTransactionStats = &(*itr);
220             return NO_ERROR;
221         }
222     }
223 
224     ALOGE("could not find transaction stats");
225     return BAD_VALUE;
226 }
227 
addCallbackHandle(const sp<CallbackHandle> & handle)228 status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
229     // If we can't find the transaction stats something has gone wrong. The client should call
230     // startRegistration before trying to add a callback handle.
231     TransactionStats* transactionStats;
232     status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
233     if (err != NO_ERROR) {
234         return err;
235     }
236 
237     transactionStats->latchTime = handle->latchTime;
238     // If the layer has already been destroyed, don't add the SurfaceControl to the callback.
239     // The client side keeps a sp<> to the SurfaceControl so if the SurfaceControl has been
240     // destroyed the client side is dead and there won't be anyone to send the callback to.
241     sp<IBinder> surfaceControl = handle->surfaceControl.promote();
242     if (surfaceControl) {
243         FrameEventHistoryStats eventStats(handle->frameNumber,
244                                           handle->gpuCompositionDoneFence->getSnapshot().fence,
245                                           handle->compositorTiming, handle->refreshStartTime,
246                                           handle->dequeueReadyTime);
247         transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
248                                                     handle->previousReleaseFence,
249                                                     handle->transformHint, eventStats);
250     }
251     return NO_ERROR;
252 }
253 
addPresentFence(const sp<Fence> & presentFence)254 void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
255     std::lock_guard<std::mutex> lock(mMutex);
256     mPresentFence = presentFence;
257 }
258 
sendCallbacks()259 void TransactionCompletedThread::sendCallbacks() {
260     std::lock_guard lock(mMutex);
261     if (mRunning) {
262         mConditionVariable.notify_all();
263     }
264 }
265 
threadMain()266 void TransactionCompletedThread::threadMain() {
267     std::lock_guard lock(mMutex);
268 
269     while (mKeepRunning) {
270         mConditionVariable.wait(mMutex);
271         std::vector<ListenerStats> completedListenerStats;
272 
273         // For each listener
274         auto completedTransactionsItr = mCompletedTransactions.begin();
275         while (completedTransactionsItr != mCompletedTransactions.end()) {
276             auto& [listener, transactionStatsDeque] = *completedTransactionsItr;
277             ListenerStats listenerStats;
278             listenerStats.listener = listener;
279 
280             // For each transaction
281             auto transactionStatsItr = transactionStatsDeque.begin();
282             while (transactionStatsItr != transactionStatsDeque.end()) {
283                 auto& transactionStats = *transactionStatsItr;
284 
285                 // If this transaction is still registering, it is not safe to send a callback
286                 // because there could be surface controls that haven't been added to
287                 // transaction stats or mPendingTransactions.
288                 if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
289                     break;
290                 }
291 
292                 // If we are still waiting on the callback handles for this transaction, stop
293                 // here because all transaction callbacks for the same listener must come in order
294                 auto pendingTransactions = mPendingTransactions.find(listener);
295                 if (pendingTransactions != mPendingTransactions.end() &&
296                     pendingTransactions->second.count(transactionStats.callbackIds) != 0) {
297                     break;
298                 }
299 
300                 // If the transaction has been latched
301                 if (transactionStats.latchTime >= 0) {
302                     if (!mPresentFence) {
303                         break;
304                     }
305                     transactionStats.presentFence = mPresentFence;
306                 }
307 
308                 // Remove the transaction from completed to the callback
309                 listenerStats.transactionStats.push_back(std::move(transactionStats));
310                 transactionStatsItr = transactionStatsDeque.erase(transactionStatsItr);
311             }
312             // If the listener has completed transactions
313             if (!listenerStats.transactionStats.empty()) {
314                 // If the listener is still alive
315                 if (listener->isBinderAlive()) {
316                     // Send callback.  The listener stored in listenerStats
317                     // comes from the cross-process setTransactionState call to
318                     // SF.  This MUST be an ITransactionCompletedListener.  We
319                     // keep it as an IBinder due to consistency reasons: if we
320                     // interface_cast at the IPC boundary when reading a Parcel,
321                     // we get pointers that compare unequal in the SF process.
322                     interface_cast<ITransactionCompletedListener>(listenerStats.listener)
323                             ->onTransactionCompleted(listenerStats);
324                     if (transactionStatsDeque.empty()) {
325                         listener->unlinkToDeath(mDeathRecipient);
326                         completedTransactionsItr =
327                                 mCompletedTransactions.erase(completedTransactionsItr);
328                     } else {
329                         completedTransactionsItr++;
330                     }
331                 } else {
332                     completedTransactionsItr =
333                             mCompletedTransactions.erase(completedTransactionsItr);
334                 }
335             } else {
336                 completedTransactionsItr++;
337             }
338 
339             completedListenerStats.push_back(std::move(listenerStats));
340         }
341 
342         if (mPresentFence) {
343             mPresentFence.clear();
344         }
345 
346         // If everyone else has dropped their reference to a layer and its listener is dead,
347         // we are about to cause the layer to be deleted. If this happens at the wrong time and
348         // we are holding mMutex, we will cause a deadlock.
349         //
350         // The deadlock happens because this thread is holding on to mMutex and when we delete
351         // the layer, it grabs SF's mStateLock. A different SF binder thread grabs mStateLock,
352         // then call's TransactionCompletedThread::run() which tries to grab mMutex.
353         //
354         // To avoid this deadlock, we need to unlock mMutex when dropping our last reference to
355         // to the layer.
356         mMutex.unlock();
357         completedListenerStats.clear();
358         mMutex.lock();
359     }
360 }
361 
362 // -----------------------------------------------------------------------
363 
CallbackHandle(const sp<IBinder> & transactionListener,const std::vector<CallbackId> & ids,const sp<IBinder> & sc)364 CallbackHandle::CallbackHandle(const sp<IBinder>& transactionListener,
365                                const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
366       : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
367 
368 } // namespace android
369 
370 // TODO(b/129481165): remove the #pragma below and fix conversion issues
371 #pragma clang diagnostic pop // ignored "-Wconversion"
372