void SurfaceFlinger::flushTransactionQueues() {
    // 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<TransactionState> transactions;
    // Layer handles that have transactions with buffers that are ready to be applied.
    std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> bufferLayersReadyToPresent;
    {
        Mutex::Autolock _l(mStateLock);
        {
            Mutex::Autolock _l(mQueueLock);
            // Collect transactions from pending transaction queue.
            auto it = mPendingTransactionQueues.begin();
            while (it != mPendingTransactionQueues.end()) {
                auto& [applyToken, transactionQueue] = *it;

                while (!transactionQueue.empty()) {
                    auto& transaction = transactionQueue.front();
                    if (!transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
                                                       transaction.isAutoTimestamp,
                                                       transaction.desiredPresentTime,
                                                       transaction.originUid, transaction.states,
                                                       bufferLayersReadyToPresent)) {
                        setTransactionFlags(eTransactionFlushNeeded);
                        break;
                    }
                    transaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
                        bufferLayersReadyToPresent.insert(state.surface);
                    });
                    transactions.emplace_back(std::move(transaction));
                    transactionQueue.pop();
                }

                if (transactionQueue.empty()) {
                    it = mPendingTransactionQueues.erase(it);
                    mTransactionQueueCV.broadcast();
                } else {
                    it = std::next(it, 1);
                }
            }
            ...
            // Collect transactions from current transaction queue or queue to pending transactions.
            // Case 1: push to pending when transactionIsReadyToBeApplied is false.
            // Case 2: push to pending when there exist a pending queue.
            // Case 3: others are ready to apply.
            while (!mTransactionQueue.empty()) {
                auto& transaction = mTransactionQueue.front();
                bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
                        mPendingTransactionQueues.end();
                if (pendingTransactions ||
                    !transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
                                                   transaction.isAutoTimestamp,
                                                   transaction.desiredPresentTime,
                                                   transaction.originUid, transaction.states,
                                                   bufferLayersReadyToPresent)) {
                    mPendingTransactionQueues[transaction.applyToken].push(std::move(transaction));
                } else {
                    transaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
                        bufferLayersReadyToPresent.insert(state.surface);
                    });
                    transactions.emplace_back(std::move(transaction));
                }
                mTransactionQueue.pop();
                ATRACE_INT("TransactionQueue", mTransactionQueue.size());
            }
        }
        // Now apply all transactions.
        for (auto& transaction : transactions) {
            applyTransactionState(transaction.frameTimelineInfo, transaction.states,
                                  transaction.displays, transaction.flags,
                                  transaction.inputWindowCommands, transaction.desiredPresentTime,
                                  transaction.isAutoTimestamp, transaction.buffer,
                                  transaction.postTime, transaction.permissions,
                                  transaction.hasListenerCallbacks, transaction.listenerCallbacks,
                                  transaction.originPid, transaction.originUid, transaction.id);
            if (transaction.transactionCommittedSignal) {
                mTransactionCommittedSignals.emplace_back(
                        std::move(transaction.transactionCommittedSignal));
            }
        }
    }
}