blob: 2c81f0ac860571eb337f45436de31f22422e67cf [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() {
33 {
34 std::lock_guard lock(mMutex);
35 mKeepRunning = false;
36 mConditionVariable.notify_all();
37 }
38
39 mThread.join();
40
41 {
42 std::lock_guard lock(mMutex);
43 for (const auto& [listener, listenerStats] : mListenerStats) {
44 listener->unlinkToDeath(mDeathRecipient);
45 }
46 }
47}
48
49void TransactionCompletedThread::run() {
50 std::lock_guard lock(mMutex);
51 if (mRunning) {
52 return;
53 }
54 mDeathRecipient = new ThreadDeathRecipient();
55 mRunning = true;
56 mThread = std::thread(&TransactionCompletedThread::threadMain, this);
57}
58
59void TransactionCompletedThread::registerPendingLatchedCallbackHandle(
60 const sp<CallbackHandle>& handle) {
61 std::lock_guard lock(mMutex);
62
63 sp<IBinder> listener = IInterface::asBinder(handle->listener);
64 const auto& callbackIds = handle->callbackIds;
65
66 mPendingTransactions[listener][callbackIds]++;
67}
68
69void TransactionCompletedThread::addLatchedCallbackHandles(
Marissa Wallfda30bb2018-10-12 11:34:28 -070070 const std::deque<sp<CallbackHandle>>& handles, nsecs_t latchTime,
71 const sp<Fence>& previousReleaseFence) {
Marissa Walle2ffb422018-10-12 11:33:52 -070072 std::lock_guard lock(mMutex);
73
Marissa Wallfda30bb2018-10-12 11:34:28 -070074 // If the previous release fences have not signaled, something as probably gone wrong.
75 // Store the fences and check them again before sending a callback.
76 if (previousReleaseFence &&
77 previousReleaseFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
78 ALOGD("release fence from the previous frame has not signaled");
79 mPreviousReleaseFences.push_back(previousReleaseFence);
80 }
81
Marissa Walle2ffb422018-10-12 11:33:52 -070082 for (const auto& handle : handles) {
83 auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener));
84 auto& pendingCallbacks = listener->second;
85 auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
86
87 if (pendingCallback != pendingCallbacks.end()) {
88 auto& pendingCount = pendingCallback->second;
89
90 // Decrease the pending count for this listener
91 if (--pendingCount == 0) {
92 pendingCallbacks.erase(pendingCallback);
93 }
94 } else {
Marissa Wallfda30bb2018-10-12 11:34:28 -070095 ALOGE("there are more latched callbacks than there were registered callbacks");
Marissa Walle2ffb422018-10-12 11:33:52 -070096 }
97
Marissa Wallfda30bb2018-10-12 11:34:28 -070098 addCallbackHandle(handle, latchTime);
Marissa Walle2ffb422018-10-12 11:33:52 -070099 }
100}
101
102void TransactionCompletedThread::addUnlatchedCallbackHandle(const sp<CallbackHandle>& handle) {
103 std::lock_guard lock(mMutex);
104 addCallbackHandle(handle);
105}
106
Marissa Wallfda30bb2018-10-12 11:34:28 -0700107void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle,
108 nsecs_t latchTime) {
Marissa Walle2ffb422018-10-12 11:33:52 -0700109 const sp<IBinder> listener = IInterface::asBinder(handle->listener);
110
111 // If we don't already have a reference to this listener, linkToDeath so we get a notification
112 // if it dies.
113 if (mListenerStats.count(listener) == 0) {
114 status_t error = listener->linkToDeath(mDeathRecipient);
115 if (error != NO_ERROR) {
116 ALOGE("cannot add callback handle because linkToDeath failed, err: %d", error);
117 return;
118 }
119 }
120
121 auto& listenerStats = mListenerStats[listener];
122 listenerStats.listener = handle->listener;
123
124 auto& transactionStats = listenerStats.transactionStats[handle->callbackIds];
Marissa Wallfda30bb2018-10-12 11:34:28 -0700125 transactionStats.latchTime = latchTime;
126 transactionStats.surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime,
127 handle->releasePreviousBuffer);
128}
129
130void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
131 std::lock_guard<std::mutex> lock(mMutex);
132 mPresentFence = presentFence;
Marissa Walle2ffb422018-10-12 11:33:52 -0700133}
134
135void TransactionCompletedThread::sendCallbacks() {
136 std::lock_guard lock(mMutex);
137 if (mRunning) {
138 mConditionVariable.notify_all();
139 }
140}
141
142void TransactionCompletedThread::threadMain() {
143 std::lock_guard lock(mMutex);
144
145 while (mKeepRunning) {
146 mConditionVariable.wait(mMutex);
147
Marissa Wallfda30bb2018-10-12 11:34:28 -0700148 // Present fence should fire almost immediately. If the fence has not signaled in 100ms,
149 // there is a major problem and it will probably never fire.
150 nsecs_t presentTime = -1;
151 if (mPresentFence) {
152 status_t status = mPresentFence->wait(100);
153 if (status == NO_ERROR) {
154 presentTime = mPresentFence->getSignalTime();
155 } else {
156 ALOGE("present fence has not signaled, err %d", status);
157 }
158 }
159
160 // We should never hit this case. The release fences from the previous frame should have
161 // signaled long before the current frame is presented.
162 for (const auto& fence : mPreviousReleaseFences) {
163 status_t status = fence->wait(100);
164 if (status != NO_ERROR) {
165 ALOGE("previous release fence has not signaled, err %d", status);
166 }
167 }
168
Marissa Walle2ffb422018-10-12 11:33:52 -0700169 // For each listener
170 auto it = mListenerStats.begin();
171 while (it != mListenerStats.end()) {
172 auto& [listener, listenerStats] = *it;
173
174 // For each transaction
175 bool sendCallback = true;
176 for (auto& [callbackIds, transactionStats] : listenerStats.transactionStats) {
177 // If we are still waiting on the callback handles for this transaction, skip it
178 if (mPendingTransactions[listener].count(callbackIds) != 0) {
179 sendCallback = false;
180 break;
181 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700182
183 // If the transaction has been latched
184 if (transactionStats.latchTime >= 0) {
185 // If the present time is < 0, this transaction has been latched but not
186 // presented. Skip it for now. This can happen when a new transaction comes
187 // in between the latch and present steps. sendCallbacks is called by
188 // SurfaceFlinger when the transaction is received to ensure that if the
189 // transaction that didn't update state it still got a callback.
190 if (presentTime < 0) {
191 sendCallback = false;
192 break;
193 }
194
195 transactionStats.presentTime = presentTime;
196 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700197 }
198 // If the listener has no pending transactions and all latched transactions have been
199 // presented
200 if (sendCallback) {
201 // If the listener is still alive
202 if (listener->isBinderAlive()) {
203 // Send callback
204 listenerStats.listener->onTransactionCompleted(listenerStats);
205 listener->unlinkToDeath(mDeathRecipient);
206 }
207 it = mListenerStats.erase(it);
208 } else {
209 it++;
210 }
211 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700212
213 if (mPresentFence) {
214 mPresentFence.clear();
215 mPreviousReleaseFences.clear();
216 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700217 }
218}
219
220// -----------------------------------------------------------------------
221
222CallbackHandle::CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
223 const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
224 : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
225
226} // namespace android