diff options
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 52 |
1 files changed, 30 insertions, 22 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2ca5c02db0..fc0d5fcb69 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3520,33 +3520,41 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, } bool SurfaceFlinger::flushTransactionQueues() { - Mutex::Autolock _l(mStateLock); + // to prevent onHandleDestroyed from being called while the lock is held, + // we must keep a copy of the transactions (specifically the composer + // states) around outside the scope of the lock + std::vector<const TransactionState> transactions; bool flushedATransaction = false; + { + Mutex::Autolock _l(mStateLock); - auto it = mTransactionQueues.begin(); - while (it != mTransactionQueues.end()) { - auto& [applyToken, transactionQueue] = *it; + auto it = mTransactionQueues.begin(); + while (it != mTransactionQueues.end()) { + auto& [applyToken, transactionQueue] = *it; - while (!transactionQueue.empty()) { - const auto& - [states, displays, flags, desiredPresentTime, uncacheBuffer, listenerCallbacks, - postTime, privileged] = transactionQueue.front(); - if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) { - setTransactionFlags(eTransactionFlushNeeded); - break; + while (!transactionQueue.empty()) { + const auto& transaction = transactionQueue.front(); + if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime, + transaction.states)) { + setTransactionFlags(eTransactionFlushNeeded); + break; + } + transactions.push_back(transaction); + applyTransactionState(transaction.states, transaction.displays, transaction.flags, + mPendingInputWindowCommands, transaction.desiredPresentTime, + transaction.buffer, transaction.callback, + transaction.postTime, transaction.privileged, + /*isMainThread*/ true); + transactionQueue.pop(); + flushedATransaction = true; } - applyTransactionState(states, displays, flags, mPendingInputWindowCommands, - desiredPresentTime, uncacheBuffer, listenerCallbacks, postTime, - privileged, /*isMainThread*/ true); - transactionQueue.pop(); - flushedATransaction = true; - } - if (transactionQueue.empty()) { - it = mTransactionQueues.erase(it); - mTransactionCV.broadcast(); - } else { - std::next(it, 1); + if (transactionQueue.empty()) { + it = mTransactionQueues.erase(it); + mTransactionCV.broadcast(); + } else { + std::next(it, 1); + } } } return flushedATransaction; |