blob: 6e0c1e2d9741c4c04796c12c14517d8f01c11af1 [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
Marissa Wall5a68a772018-12-22 17:43:42 -080065void TransactionCompletedThread::registerPendingCallbackHandle(const sp<CallbackHandle>& handle) {
Marissa Walle2ffb422018-10-12 11:33:52 -070066 std::lock_guard lock(mMutex);
67
68 sp<IBinder> listener = IInterface::asBinder(handle->listener);
69 const auto& callbackIds = handle->callbackIds;
70
71 mPendingTransactions[listener][callbackIds]++;
72}
73
Marissa Wall5a68a772018-12-22 17:43:42 -080074void TransactionCompletedThread::addPresentedCallbackHandles(
75 const std::deque<sp<CallbackHandle>>& handles) {
Marissa Walle2ffb422018-10-12 11:33:52 -070076 std::lock_guard lock(mMutex);
77
78 for (const auto& handle : handles) {
79 auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener));
80 auto& pendingCallbacks = listener->second;
81 auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
82
83 if (pendingCallback != pendingCallbacks.end()) {
84 auto& pendingCount = pendingCallback->second;
85
86 // Decrease the pending count for this listener
87 if (--pendingCount == 0) {
88 pendingCallbacks.erase(pendingCallback);
89 }
90 } else {
Marissa Wallfda30bb2018-10-12 11:34:28 -070091 ALOGE("there are more latched callbacks than there were registered callbacks");
Marissa Walle2ffb422018-10-12 11:33:52 -070092 }
93
Marissa Wall5a68a772018-12-22 17:43:42 -080094 addCallbackHandle(handle);
Marissa Walle2ffb422018-10-12 11:33:52 -070095 }
96}
97
Marissa Wall5a68a772018-12-22 17:43:42 -080098void TransactionCompletedThread::addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle) {
Marissa Walle2ffb422018-10-12 11:33:52 -070099 std::lock_guard lock(mMutex);
100 addCallbackHandle(handle);
101}
102
Marissa Wall3dad52d2019-03-22 14:03:19 -0700103void TransactionCompletedThread::addCallback(
104 const sp<ITransactionCompletedListener>& transactionListener,
105 const std::vector<CallbackId>& callbackIds) {
106 std::lock_guard lock(mMutex);
107 addCallbackLocked(transactionListener, callbackIds);
108}
Marissa Walle2ffb422018-10-12 11:33:52 -0700109
Marissa Wall3dad52d2019-03-22 14:03:19 -0700110status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
111 status_t err = addCallbackLocked(handle->listener, handle->callbackIds);
112 if (err != NO_ERROR) {
113 ALOGE("cannot add callback, err: %d", err);
114 return err;
115 }
116
117 const sp<IBinder> listener = IInterface::asBinder(handle->listener);
118 auto& listenerStats = mListenerStats[listener];
119 auto& transactionStats = listenerStats.transactionStats[handle->callbackIds];
120
121 transactionStats.latchTime = handle->latchTime;
122 transactionStats.surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime,
123 handle->previousReleaseFence);
124 return NO_ERROR;
125}
126
127status_t TransactionCompletedThread::addCallbackLocked(
128 const sp<ITransactionCompletedListener>& transactionListener,
129 const std::vector<CallbackId>& callbackIds) {
130 const sp<IBinder> listener = IInterface::asBinder(transactionListener);
Marissa Walle2ffb422018-10-12 11:33:52 -0700131 // If we don't already have a reference to this listener, linkToDeath so we get a notification
132 // if it dies.
133 if (mListenerStats.count(listener) == 0) {
Marissa Wall3dad52d2019-03-22 14:03:19 -0700134 status_t err = listener->linkToDeath(mDeathRecipient);
135 if (err != NO_ERROR) {
136 ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
137 return err;
Marissa Walle2ffb422018-10-12 11:33:52 -0700138 }
139 }
140
141 auto& listenerStats = mListenerStats[listener];
Marissa Wall3dad52d2019-03-22 14:03:19 -0700142 listenerStats.listener = transactionListener;
143 listenerStats.transactionStats[callbackIds];
144 return NO_ERROR;
Marissa Wallfda30bb2018-10-12 11:34:28 -0700145}
146
147void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
148 std::lock_guard<std::mutex> lock(mMutex);
149 mPresentFence = presentFence;
Marissa Walle2ffb422018-10-12 11:33:52 -0700150}
151
152void TransactionCompletedThread::sendCallbacks() {
153 std::lock_guard lock(mMutex);
154 if (mRunning) {
155 mConditionVariable.notify_all();
156 }
157}
158
159void TransactionCompletedThread::threadMain() {
160 std::lock_guard lock(mMutex);
161
162 while (mKeepRunning) {
163 mConditionVariable.wait(mMutex);
164
165 // For each listener
166 auto it = mListenerStats.begin();
167 while (it != mListenerStats.end()) {
168 auto& [listener, listenerStats] = *it;
169
170 // For each transaction
171 bool sendCallback = true;
172 for (auto& [callbackIds, transactionStats] : listenerStats.transactionStats) {
173 // If we are still waiting on the callback handles for this transaction, skip it
174 if (mPendingTransactions[listener].count(callbackIds) != 0) {
175 sendCallback = false;
176 break;
177 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700178
179 // If the transaction has been latched
180 if (transactionStats.latchTime >= 0) {
Valerie Hau63258a12018-12-14 14:31:48 -0800181 if (!mPresentFence) {
Marissa Wallfda30bb2018-10-12 11:34:28 -0700182 sendCallback = false;
183 break;
184 }
Valerie Hau63258a12018-12-14 14:31:48 -0800185 transactionStats.presentFence = mPresentFence;
Marissa Wallfda30bb2018-10-12 11:34:28 -0700186 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700187 }
188 // If the listener has no pending transactions and all latched transactions have been
189 // presented
190 if (sendCallback) {
191 // If the listener is still alive
192 if (listener->isBinderAlive()) {
193 // Send callback
194 listenerStats.listener->onTransactionCompleted(listenerStats);
195 listener->unlinkToDeath(mDeathRecipient);
196 }
197 it = mListenerStats.erase(it);
198 } else {
199 it++;
200 }
201 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700202
203 if (mPresentFence) {
204 mPresentFence.clear();
Marissa Wallfda30bb2018-10-12 11:34:28 -0700205 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700206 }
207}
208
209// -----------------------------------------------------------------------
210
211CallbackHandle::CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
212 const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
213 : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
214
215} // namespace android