| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 1 | /* | 
|  | 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 |  | 
|  | 30 | namespace android { | 
|  | 31 |  | 
|  | 32 | TransactionCompletedThread::~TransactionCompletedThread() { | 
| Marissa Wall | 99343ba | 2018-11-13 10:39:08 -0800 | [diff] [blame] | 33 | std::lock_guard lockThread(mThreadMutex); | 
|  | 34 |  | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 35 | { | 
|  | 36 | std::lock_guard lock(mMutex); | 
|  | 37 | mKeepRunning = false; | 
|  | 38 | mConditionVariable.notify_all(); | 
|  | 39 | } | 
|  | 40 |  | 
| Marissa Wall | 05d9dd3 | 2018-11-13 10:05:14 -0800 | [diff] [blame] | 41 | if (mThread.joinable()) { | 
|  | 42 | mThread.join(); | 
|  | 43 | } | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 44 |  | 
|  | 45 | { | 
|  | 46 | std::lock_guard lock(mMutex); | 
|  | 47 | for (const auto& [listener, listenerStats] : mListenerStats) { | 
|  | 48 | listener->unlinkToDeath(mDeathRecipient); | 
|  | 49 | } | 
|  | 50 | } | 
|  | 51 | } | 
|  | 52 |  | 
|  | 53 | void TransactionCompletedThread::run() { | 
|  | 54 | std::lock_guard lock(mMutex); | 
| Marissa Wall | 99343ba | 2018-11-13 10:39:08 -0800 | [diff] [blame] | 55 | if (mRunning || !mKeepRunning) { | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 56 | return; | 
|  | 57 | } | 
|  | 58 | mDeathRecipient = new ThreadDeathRecipient(); | 
|  | 59 | mRunning = true; | 
| Marissa Wall | 99343ba | 2018-11-13 10:39:08 -0800 | [diff] [blame] | 60 |  | 
|  | 61 | std::lock_guard lockThread(mThreadMutex); | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 62 | mThread = std::thread(&TransactionCompletedThread::threadMain, this); | 
|  | 63 | } | 
|  | 64 |  | 
| Marissa Wall | 5a68a77 | 2018-12-22 17:43:42 -0800 | [diff] [blame] | 65 | void TransactionCompletedThread::registerPendingCallbackHandle(const sp<CallbackHandle>& handle) { | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 66 | 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 Wall | 5a68a77 | 2018-12-22 17:43:42 -0800 | [diff] [blame] | 74 | void TransactionCompletedThread::addPresentedCallbackHandles( | 
|  | 75 | const std::deque<sp<CallbackHandle>>& handles) { | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 76 | 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 Wall | fda30bb | 2018-10-12 11:34:28 -0700 | [diff] [blame] | 91 | ALOGE("there are more latched callbacks than there were registered callbacks"); | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 92 | } | 
|  | 93 |  | 
| Marissa Wall | 5a68a77 | 2018-12-22 17:43:42 -0800 | [diff] [blame] | 94 | addCallbackHandle(handle); | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 95 | } | 
|  | 96 | } | 
|  | 97 |  | 
| Marissa Wall | 5a68a77 | 2018-12-22 17:43:42 -0800 | [diff] [blame] | 98 | void TransactionCompletedThread::addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle) { | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 99 | std::lock_guard lock(mMutex); | 
|  | 100 | addCallbackHandle(handle); | 
|  | 101 | } | 
|  | 102 |  | 
| Marissa Wall | 5a68a77 | 2018-12-22 17:43:42 -0800 | [diff] [blame] | 103 | void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) { | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 104 | 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 Wall | 5a68a77 | 2018-12-22 17:43:42 -0800 | [diff] [blame] | 120 | transactionStats.latchTime = handle->latchTime; | 
| Marissa Wall | fda30bb | 2018-10-12 11:34:28 -0700 | [diff] [blame] | 121 | transactionStats.surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime, | 
| Marissa Wall | 5a68a77 | 2018-12-22 17:43:42 -0800 | [diff] [blame] | 122 | handle->previousReleaseFence); | 
| Marissa Wall | fda30bb | 2018-10-12 11:34:28 -0700 | [diff] [blame] | 123 | } | 
|  | 124 |  | 
|  | 125 | void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) { | 
|  | 126 | std::lock_guard<std::mutex> lock(mMutex); | 
|  | 127 | mPresentFence = presentFence; | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 128 | } | 
|  | 129 |  | 
|  | 130 | void TransactionCompletedThread::sendCallbacks() { | 
|  | 131 | std::lock_guard lock(mMutex); | 
|  | 132 | if (mRunning) { | 
|  | 133 | mConditionVariable.notify_all(); | 
|  | 134 | } | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | void 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 Wall | fda30bb | 2018-10-12 11:34:28 -0700 | [diff] [blame] | 156 |  | 
|  | 157 | // If the transaction has been latched | 
|  | 158 | if (transactionStats.latchTime >= 0) { | 
| Valerie Hau | 63258a1 | 2018-12-14 14:31:48 -0800 | [diff] [blame] | 159 | if (!mPresentFence) { | 
| Marissa Wall | fda30bb | 2018-10-12 11:34:28 -0700 | [diff] [blame] | 160 | sendCallback = false; | 
|  | 161 | break; | 
|  | 162 | } | 
| Valerie Hau | 63258a1 | 2018-12-14 14:31:48 -0800 | [diff] [blame] | 163 | transactionStats.presentFence = mPresentFence; | 
| Marissa Wall | fda30bb | 2018-10-12 11:34:28 -0700 | [diff] [blame] | 164 | } | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 165 | } | 
|  | 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 Wall | fda30bb | 2018-10-12 11:34:28 -0700 | [diff] [blame] | 180 |  | 
|  | 181 | if (mPresentFence) { | 
|  | 182 | mPresentFence.clear(); | 
| Marissa Wall | fda30bb | 2018-10-12 11:34:28 -0700 | [diff] [blame] | 183 | } | 
| Marissa Wall | e2ffb42 | 2018-10-12 11:33:52 -0700 | [diff] [blame] | 184 | } | 
|  | 185 | } | 
|  | 186 |  | 
|  | 187 | // ----------------------------------------------------------------------- | 
|  | 188 |  | 
|  | 189 | CallbackHandle::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 |