blob: d2b7fe099f3f691d47653e00f040e9071c80bcab [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 Wall5a68a772018-12-22 17:43:42 -0800103void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
Marissa Walle2ffb422018-10-12 11:33:52 -0700104 const sp<IBinder> listener = IInterface::asBinder(handle->listener);
105
106 // If we don't already have a reference to this listener, linkToDeath so we get a notification
107 // if it dies.
108 if (mListenerStats.count(listener) == 0) {
109 status_t error = listener->linkToDeath(mDeathRecipient);
110 if (error != NO_ERROR) {
111 ALOGE("cannot add callback handle because linkToDeath failed, err: %d", error);
112 return;
113 }
114 }
115
116 auto& listenerStats = mListenerStats[listener];
117 listenerStats.listener = handle->listener;
118
119 auto& transactionStats = listenerStats.transactionStats[handle->callbackIds];
Marissa Wall5a68a772018-12-22 17:43:42 -0800120 transactionStats.latchTime = handle->latchTime;
Marissa Wallfda30bb2018-10-12 11:34:28 -0700121 transactionStats.surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime,
Marissa Wall5a68a772018-12-22 17:43:42 -0800122 handle->previousReleaseFence);
Marissa Wallfda30bb2018-10-12 11:34:28 -0700123}
124
125void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
126 std::lock_guard<std::mutex> lock(mMutex);
127 mPresentFence = presentFence;
Marissa Walle2ffb422018-10-12 11:33:52 -0700128}
129
130void TransactionCompletedThread::sendCallbacks() {
131 std::lock_guard lock(mMutex);
132 if (mRunning) {
133 mConditionVariable.notify_all();
134 }
135}
136
137void TransactionCompletedThread::threadMain() {
138 std::lock_guard lock(mMutex);
139
140 while (mKeepRunning) {
141 mConditionVariable.wait(mMutex);
142
143 // For each listener
144 auto it = mListenerStats.begin();
145 while (it != mListenerStats.end()) {
146 auto& [listener, listenerStats] = *it;
147
148 // For each transaction
149 bool sendCallback = true;
150 for (auto& [callbackIds, transactionStats] : listenerStats.transactionStats) {
151 // If we are still waiting on the callback handles for this transaction, skip it
152 if (mPendingTransactions[listener].count(callbackIds) != 0) {
153 sendCallback = false;
154 break;
155 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700156
157 // If the transaction has been latched
158 if (transactionStats.latchTime >= 0) {
Valerie Hau63258a12018-12-14 14:31:48 -0800159 if (!mPresentFence) {
Marissa Wallfda30bb2018-10-12 11:34:28 -0700160 sendCallback = false;
161 break;
162 }
Valerie Hau63258a12018-12-14 14:31:48 -0800163 transactionStats.presentFence = mPresentFence;
Marissa Wallfda30bb2018-10-12 11:34:28 -0700164 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700165 }
166 // If the listener has no pending transactions and all latched transactions have been
167 // presented
168 if (sendCallback) {
169 // If the listener is still alive
170 if (listener->isBinderAlive()) {
171 // Send callback
172 listenerStats.listener->onTransactionCompleted(listenerStats);
173 listener->unlinkToDeath(mDeathRecipient);
174 }
175 it = mListenerStats.erase(it);
176 } else {
177 it++;
178 }
179 }
Marissa Wallfda30bb2018-10-12 11:34:28 -0700180
181 if (mPresentFence) {
182 mPresentFence.clear();
Marissa Wallfda30bb2018-10-12 11:34:28 -0700183 }
Marissa Walle2ffb422018-10-12 11:33:52 -0700184 }
185}
186
187// -----------------------------------------------------------------------
188
189CallbackHandle::CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
190 const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
191 : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
192
193} // namespace android