blob: a1a86923f38fffe3cbffd41fccf4be996284fce7 [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 // We should never hit this case. The release fences from the previous frame should have
155 // signaled long before the current frame is presented.
156 for (const auto& fence : mPreviousReleaseFences) {
157 status_t status = fence->wait(100);
158 if (status != NO_ERROR) {
159 ALOGE("previous release fence has not signaled, err %d", status);
160 }
161 }
162
Marissa Walle2ffb422018-10-12 11:33:52 -0700163 // For each listener
164 auto it = mListenerStats.begin();
165 while (it != mListenerStats.end()) {
166 auto& [listener, listenerStats] = *it;
167
168 // For each transaction
169 bool sendCallback = true;
170 for (auto& [callbackIds, transactionStats] : listenerStats.transactionStats) {
171 // If we are still waiting on the callback handles for this transaction, skip it
172 if (mPendingTransactions[listener].count(callbackIds) != 0) {
173 sendCallback = false;
174 break;
175 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700176
177 // If the transaction has been latched
178 if (transactionStats.latchTime >= 0) {
Valerie Hau63258a12018-12-14 14:31:48 -0800179 if (!mPresentFence) {
Marissa Wallfda30bb2018-10-12 11:34:28 -0700180 sendCallback = false;
181 break;
182 }
Valerie Hau63258a12018-12-14 14:31:48 -0800183 transactionStats.presentFence = mPresentFence;
Marissa Wallfda30bb2018-10-12 11:34:28 -0700184 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700185 }
186 // If the listener has no pending transactions and all latched transactions have been
187 // presented
188 if (sendCallback) {
189 // If the listener is still alive
190 if (listener->isBinderAlive()) {
191 // Send callback
192 listenerStats.listener->onTransactionCompleted(listenerStats);
193 listener->unlinkToDeath(mDeathRecipient);
194 }
195 it = mListenerStats.erase(it);
196 } else {
197 it++;
198 }
199 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700200
201 if (mPresentFence) {
202 mPresentFence.clear();
203 mPreviousReleaseFences.clear();
204 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700205 }
206}
207
208// -----------------------------------------------------------------------
209
210CallbackHandle::CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
211 const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
212 : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
213
214} // namespace android