blob: e83422e23b25c4bdd907bb2a0ea0320b4303bad0 [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(
70 const std::deque<sp<CallbackHandle>>& handles) {
71 std::lock_guard lock(mMutex);
72
73 for (const auto& handle : handles) {
74 auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener));
75 auto& pendingCallbacks = listener->second;
76 auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
77
78 if (pendingCallback != pendingCallbacks.end()) {
79 auto& pendingCount = pendingCallback->second;
80
81 // Decrease the pending count for this listener
82 if (--pendingCount == 0) {
83 pendingCallbacks.erase(pendingCallback);
84 }
85 } else {
86 ALOGW("there are more latched callbacks than there were registered callbacks");
87 }
88
89 addCallbackHandle(handle);
90 }
91}
92
93void TransactionCompletedThread::addUnlatchedCallbackHandle(const sp<CallbackHandle>& handle) {
94 std::lock_guard lock(mMutex);
95 addCallbackHandle(handle);
96}
97
98void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
99 const sp<IBinder> listener = IInterface::asBinder(handle->listener);
100
101 // If we don't already have a reference to this listener, linkToDeath so we get a notification
102 // if it dies.
103 if (mListenerStats.count(listener) == 0) {
104 status_t error = listener->linkToDeath(mDeathRecipient);
105 if (error != NO_ERROR) {
106 ALOGE("cannot add callback handle because linkToDeath failed, err: %d", error);
107 return;
108 }
109 }
110
111 auto& listenerStats = mListenerStats[listener];
112 listenerStats.listener = handle->listener;
113
114 auto& transactionStats = listenerStats.transactionStats[handle->callbackIds];
115 transactionStats.surfaceStats.emplace_back(handle->surfaceControl);
116}
117
118void TransactionCompletedThread::sendCallbacks() {
119 std::lock_guard lock(mMutex);
120 if (mRunning) {
121 mConditionVariable.notify_all();
122 }
123}
124
125void TransactionCompletedThread::threadMain() {
126 std::lock_guard lock(mMutex);
127
128 while (mKeepRunning) {
129 mConditionVariable.wait(mMutex);
130
131 // For each listener
132 auto it = mListenerStats.begin();
133 while (it != mListenerStats.end()) {
134 auto& [listener, listenerStats] = *it;
135
136 // For each transaction
137 bool sendCallback = true;
138 for (auto& [callbackIds, transactionStats] : listenerStats.transactionStats) {
139 // If we are still waiting on the callback handles for this transaction, skip it
140 if (mPendingTransactions[listener].count(callbackIds) != 0) {
141 sendCallback = false;
142 break;
143 }
144 }
145 // If the listener has no pending transactions and all latched transactions have been
146 // presented
147 if (sendCallback) {
148 // If the listener is still alive
149 if (listener->isBinderAlive()) {
150 // Send callback
151 listenerStats.listener->onTransactionCompleted(listenerStats);
152 listener->unlinkToDeath(mDeathRecipient);
153 }
154 it = mListenerStats.erase(it);
155 } else {
156 it++;
157 }
158 }
159 }
160}
161
162// -----------------------------------------------------------------------
163
164CallbackHandle::CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
165 const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
166 : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
167
168} // namespace android