blob: 389118a0d7373ec05a6b262a5716c5d13e8c7669 [file] [log] [blame]
Marissa Walle2ffb422018-10-12 11:33:52 -07001/*
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
30namespace android {
31
32TransactionCompletedThread::~TransactionCompletedThread() {
Marissa Wall99343ba2018-11-13 10:39:08 -080033 std::lock_guard lockThread(mThreadMutex);
34
Marissa Walle2ffb422018-10-12 11:33:52 -070035 {
36 std::lock_guard lock(mMutex);
37 mKeepRunning = false;
38 mConditionVariable.notify_all();
39 }
40
Marissa Wall05d9dd32018-11-13 10:05:14 -080041 if (mThread.joinable()) {
42 mThread.join();
43 }
Marissa Walle2ffb422018-10-12 11:33:52 -070044
45 {
46 std::lock_guard lock(mMutex);
47 for (const auto& [listener, listenerStats] : mListenerStats) {
48 listener->unlinkToDeath(mDeathRecipient);
49 }
50 }
51}
52
53void TransactionCompletedThread::run() {
54 std::lock_guard lock(mMutex);
Marissa Wall99343ba2018-11-13 10:39:08 -080055 if (mRunning || !mKeepRunning) {
Marissa Walle2ffb422018-10-12 11:33:52 -070056 return;
57 }
58 mDeathRecipient = new ThreadDeathRecipient();
59 mRunning = true;
Marissa Wall99343ba2018-11-13 10:39:08 -080060
61 std::lock_guard lockThread(mThreadMutex);
Marissa Walle2ffb422018-10-12 11:33:52 -070062 mThread = std::thread(&TransactionCompletedThread::threadMain, this);
63}
64
65void TransactionCompletedThread::registerPendingLatchedCallbackHandle(
66 const sp<CallbackHandle>& handle) {
67 std::lock_guard lock(mMutex);
68
69 sp<IBinder> listener = IInterface::asBinder(handle->listener);
70 const auto& callbackIds = handle->callbackIds;
71
72 mPendingTransactions[listener][callbackIds]++;
73}
74
75void TransactionCompletedThread::addLatchedCallbackHandles(
Marissa Wallfda30bb2018-10-12 11:34:28 -070076 const std::deque<sp<CallbackHandle>>& handles, nsecs_t latchTime,
77 const sp<Fence>& previousReleaseFence) {
Marissa Walle2ffb422018-10-12 11:33:52 -070078 std::lock_guard lock(mMutex);
79
Marissa Wallfda30bb2018-10-12 11:34:28 -070080 // If the previous release fences have not signaled, something as probably gone wrong.
81 // Store the fences and check them again before sending a callback.
82 if (previousReleaseFence &&
83 previousReleaseFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
84 ALOGD("release fence from the previous frame has not signaled");
85 mPreviousReleaseFences.push_back(previousReleaseFence);
86 }
87
Marissa Walle2ffb422018-10-12 11:33:52 -070088 for (const auto& handle : handles) {
89 auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener));
90 auto& pendingCallbacks = listener->second;
91 auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
92
93 if (pendingCallback != pendingCallbacks.end()) {
94 auto& pendingCount = pendingCallback->second;
95
96 // Decrease the pending count for this listener
97 if (--pendingCount == 0) {
98 pendingCallbacks.erase(pendingCallback);
99 }
100 } else {
Marissa Wallfda30bb2018-10-12 11:34:28 -0700101 ALOGE("there are more latched callbacks than there were registered callbacks");
Marissa Walle2ffb422018-10-12 11:33:52 -0700102 }
103
Marissa Wallfda30bb2018-10-12 11:34:28 -0700104 addCallbackHandle(handle, latchTime);
Marissa Walle2ffb422018-10-12 11:33:52 -0700105 }
106}
107
108void TransactionCompletedThread::addUnlatchedCallbackHandle(const sp<CallbackHandle>& handle) {
109 std::lock_guard lock(mMutex);
110 addCallbackHandle(handle);
111}
112
Marissa Wallfda30bb2018-10-12 11:34:28 -0700113void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle,
114 nsecs_t latchTime) {
Marissa Walle2ffb422018-10-12 11:33:52 -0700115 const sp<IBinder> listener = IInterface::asBinder(handle->listener);
116
117 // If we don't already have a reference to this listener, linkToDeath so we get a notification
118 // if it dies.
119 if (mListenerStats.count(listener) == 0) {
120 status_t error = listener->linkToDeath(mDeathRecipient);
121 if (error != NO_ERROR) {
122 ALOGE("cannot add callback handle because linkToDeath failed, err: %d", error);
123 return;
124 }
125 }
126
127 auto& listenerStats = mListenerStats[listener];
128 listenerStats.listener = handle->listener;
129
130 auto& transactionStats = listenerStats.transactionStats[handle->callbackIds];
Marissa Wallfda30bb2018-10-12 11:34:28 -0700131 transactionStats.latchTime = latchTime;
132 transactionStats.surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime,
133 handle->releasePreviousBuffer);
134}
135
136void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
137 std::lock_guard<std::mutex> lock(mMutex);
138 mPresentFence = presentFence;
Marissa Walle2ffb422018-10-12 11:33:52 -0700139}
140
141void TransactionCompletedThread::sendCallbacks() {
142 std::lock_guard lock(mMutex);
143 if (mRunning) {
144 mConditionVariable.notify_all();
145 }
146}
147
148void TransactionCompletedThread::threadMain() {
149 std::lock_guard lock(mMutex);
150
151 while (mKeepRunning) {
152 mConditionVariable.wait(mMutex);
153
Marissa Wallfda30bb2018-10-12 11:34:28 -0700154 // Present fence should fire almost immediately. If the fence has not signaled in 100ms,
155 // there is a major problem and it will probably never fire.
156 nsecs_t presentTime = -1;
157 if (mPresentFence) {
158 status_t status = mPresentFence->wait(100);
159 if (status == NO_ERROR) {
160 presentTime = mPresentFence->getSignalTime();
161 } else {
162 ALOGE("present fence has not signaled, err %d", status);
163 }
164 }
165
166 // We should never hit this case. The release fences from the previous frame should have
167 // signaled long before the current frame is presented.
168 for (const auto& fence : mPreviousReleaseFences) {
169 status_t status = fence->wait(100);
170 if (status != NO_ERROR) {
171 ALOGE("previous release fence has not signaled, err %d", status);
172 }
173 }
174
Marissa Walle2ffb422018-10-12 11:33:52 -0700175 // For each listener
176 auto it = mListenerStats.begin();
177 while (it != mListenerStats.end()) {
178 auto& [listener, listenerStats] = *it;
179
180 // For each transaction
181 bool sendCallback = true;
182 for (auto& [callbackIds, transactionStats] : listenerStats.transactionStats) {
183 // If we are still waiting on the callback handles for this transaction, skip it
184 if (mPendingTransactions[listener].count(callbackIds) != 0) {
185 sendCallback = false;
186 break;
187 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700188
189 // If the transaction has been latched
190 if (transactionStats.latchTime >= 0) {
191 // If the present time is < 0, this transaction has been latched but not
192 // presented. Skip it for now. This can happen when a new transaction comes
193 // in between the latch and present steps. sendCallbacks is called by
194 // SurfaceFlinger when the transaction is received to ensure that if the
195 // transaction that didn't update state it still got a callback.
196 if (presentTime < 0) {
197 sendCallback = false;
198 break;
199 }
200
201 transactionStats.presentTime = presentTime;
202 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700203 }
204 // If the listener has no pending transactions and all latched transactions have been
205 // presented
206 if (sendCallback) {
207 // If the listener is still alive
208 if (listener->isBinderAlive()) {
209 // Send callback
210 listenerStats.listener->onTransactionCompleted(listenerStats);
211 listener->unlinkToDeath(mDeathRecipient);
212 }
213 it = mListenerStats.erase(it);
214 } else {
215 it++;
216 }
217 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700218
219 if (mPresentFence) {
220 mPresentFence.clear();
221 mPreviousReleaseFences.clear();
222 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700223 }
224}
225
226// -----------------------------------------------------------------------
227
228CallbackHandle::CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
229 const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
230 : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
231
232} // namespace android