| 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 |