Loading services/surfaceflinger/SurfaceFlinger.cpp +72 −56 Original line number Original line Diff line number Diff line Loading @@ -3647,19 +3647,11 @@ bool SurfaceFlinger::stopTransactionProcessing( return false; return false; } } bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { void SurfaceFlinger::flushPendingTransactionQueues( // to prevent onHandleDestroyed from being called while the lock is held, std::vector<TransactionState>& transactions, // we must keep a copy of the transactions (specifically the composer std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, // states) around outside the scope of the lock std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions, std::vector<TransactionState> transactions; bool tryApplyUnsignaled) { // Layer handles that have transactions with buffers that are ready to be applied. std::unordered_set<sp<IBinder>, SpHash<IBinder>> bufferLayersReadyToPresent; std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions; { Mutex::Autolock _l(mStateLock); { Mutex::Autolock _l(mQueueLock); // Collect transactions from pending transaction queue. auto it = mPendingTransactionQueues.begin(); auto it = mPendingTransactionQueues.begin(); while (it != mPendingTransactionQueues.end()) { while (it != mPendingTransactionQueues.end()) { auto& [applyToken, transactionQueue] = *it; auto& [applyToken, transactionQueue] = *it; Loading @@ -3675,8 +3667,8 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { transaction.isAutoTimestamp, transaction.isAutoTimestamp, transaction.desiredPresentTime, transaction.desiredPresentTime, transaction.originUid, transaction.states, transaction.originUid, transaction.states, bufferLayersReadyToPresent, bufferLayersReadyToPresent, transactions.size(), transactions.size()); tryApplyUnsignaled); ATRACE_INT("TransactionReadiness", static_cast<int>(ready)); ATRACE_INT("TransactionReadiness", static_cast<int>(ready)); if (ready == TransactionReadiness::NotReady) { if (ready == TransactionReadiness::NotReady) { setTransactionFlags(eTransactionFlushNeeded); setTransactionFlags(eTransactionFlushNeeded); Loading @@ -3701,21 +3693,39 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { it = std::next(it, 1); it = std::next(it, 1); } } } } } bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { // 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>, SpHash<IBinder>> bufferLayersReadyToPresent; std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions; { Mutex::Autolock _l(mStateLock); { Mutex::Autolock _l(mQueueLock); // First collect transactions from the pending transaction queues. // We are not allowing unsignaled buffers here as we want to // collect all the transactions from applyTokens that are ready first. flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent, applyTokensWithUnsignaledTransactions, /*tryApplyUnsignaled*/ false); // Collect transactions from current transaction queue or queue to pending transactions. // Second, collect transactions from the transaction queue. // Case 1: push to pending when transactionIsReadyToBeApplied is false // Here as well we are not allowing unsignaled buffers for the same // or the first transaction was unsignaled. // reason as above. // Case 2: push to pending when there exist a pending queue. // Case 3: others are the transactions that are ready to apply. while (!mTransactionQueue.empty()) { while (!mTransactionQueue.empty()) { auto& transaction = mTransactionQueue.front(); auto& transaction = mTransactionQueue.front(); const bool pendingTransactions = const bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) != mPendingTransactionQueues.find(transaction.applyToken) != mPendingTransactionQueues.end(); mPendingTransactionQueues.end(); const auto ready = [&]() REQUIRES(mStateLock) { const auto ready = [&]() REQUIRES(mStateLock) { if (pendingTransactions || if (pendingTransactions) { stopTransactionProcessing(applyTokensWithUnsignaledTransactions)) { ATRACE_NAME("pendingTransactions"); ATRACE_NAME("pendingTransactions || stopTransactionProcessing"); return TransactionReadiness::NotReady; return TransactionReadiness::NotReady; } } Loading @@ -3724,7 +3734,8 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { transaction.desiredPresentTime, transaction.desiredPresentTime, transaction.originUid, transaction.states, transaction.originUid, transaction.states, bufferLayersReadyToPresent, bufferLayersReadyToPresent, transactions.size()); transactions.size(), /*tryApplyUnsignaled*/ false); }(); }(); ATRACE_INT("TransactionReadiness", static_cast<int>(ready)); ATRACE_INT("TransactionReadiness", static_cast<int>(ready)); if (ready == TransactionReadiness::NotReady) { if (ready == TransactionReadiness::NotReady) { Loading @@ -3733,16 +3744,21 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { transaction.traverseStatesWithBuffers([&](const layer_state_t& state) { transaction.traverseStatesWithBuffers([&](const layer_state_t& state) { bufferLayersReadyToPresent.insert(state.surface); bufferLayersReadyToPresent.insert(state.surface); }); }); const bool appliedUnsignaled = (ready == TransactionReadiness::ReadyUnsignaled); if (appliedUnsignaled) { applyTokensWithUnsignaledTransactions.insert(transaction.applyToken); } transactions.emplace_back(std::move(transaction)); transactions.emplace_back(std::move(transaction)); } } mTransactionQueue.pop_front(); mTransactionQueue.pop_front(); ATRACE_INT("TransactionQueue", mTransactionQueue.size()); ATRACE_INT("TransactionQueue", mTransactionQueue.size()); } } // We collected all transactions that could apply without latching unsignaled buffers. // If we are allowing latch unsignaled of some form, now it's the time to go over the // transactions that were not applied and try to apply them unsignaled. if (enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) { flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent, applyTokensWithUnsignaledTransactions, /*tryApplyUnsignaled*/ true); } return applyTransactions(transactions, vsyncId); return applyTransactions(transactions, vsyncId); } } } } Loading Loading @@ -3850,7 +3866,7 @@ auto SurfaceFlinger::transactionIsReadyToBeApplied( const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, uid_t originUid, const Vector<ComposerState>& states, uid_t originUid, const Vector<ComposerState>& states, const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, size_t totalTXapplied) const -> TransactionReadiness { size_t totalTXapplied, bool tryApplyUnsignaled) const -> TransactionReadiness { ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId); ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId); const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); // Do not present if the desiredPresentTime has not passed unless it is more than one second // Do not present if the desiredPresentTime has not passed unless it is more than one second Loading Loading @@ -3887,7 +3903,7 @@ auto SurfaceFlinger::transactionIsReadyToBeApplied( continue; continue; } } const bool allowLatchUnsignaled = const bool allowLatchUnsignaled = tryApplyUnsignaled && shouldLatchUnsignaled(layer, s, states.size(), totalTXapplied); shouldLatchUnsignaled(layer, s, states.size(), totalTXapplied); ATRACE_FORMAT("%s allowLatchUnsignaled=%s", layer->getName().c_str(), ATRACE_FORMAT("%s allowLatchUnsignaled=%s", layer->getName().c_str(), allowLatchUnsignaled ? "true" : "false"); allowLatchUnsignaled ? "true" : "false"); Loading services/surfaceflinger/SurfaceFlinger.h +7 −1 Original line number Original line Diff line number Diff line Loading @@ -750,6 +750,12 @@ private: // Returns true if there is at least one transaction that needs to be flushed // Returns true if there is at least one transaction that needs to be flushed bool transactionFlushNeeded(); bool transactionFlushNeeded(); void flushPendingTransactionQueues( std::vector<TransactionState>& transactions, std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions, bool tryApplyUnsignaled) REQUIRES(mStateLock, mQueueLock); uint32_t setClientStateLocked(const FrameTimelineInfo&, ComposerState&, uint32_t setClientStateLocked(const FrameTimelineInfo&, ComposerState&, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, uint32_t permissions) REQUIRES(mStateLock); int64_t postTime, uint32_t permissions) REQUIRES(mStateLock); Loading Loading @@ -780,7 +786,7 @@ private: const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, uid_t originUid, const Vector<ComposerState>& states, uid_t originUid, const Vector<ComposerState>& states, const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, size_t totalTXapplied) const REQUIRES(mStateLock); size_t totalTXapplied, bool tryApplyUnsignaled) const REQUIRES(mStateLock); static LatchUnsignaledConfig getLatchUnsignaledConfig(); static LatchUnsignaledConfig getLatchUnsignaledConfig(); bool shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t&, size_t numStates, bool shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t&, size_t numStates, size_t totalTXapplied) const; size_t totalTXapplied) const; Loading services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +52 −5 Original line number Original line Diff line number Diff line Loading @@ -551,13 +551,52 @@ TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSignaledFromTheQueue) { kExpectedTransactionsPending); kExpectedTransactionsPending); } } TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemoveSignaledWithUnsignaledIntact) { TEST_F(LatchUnsignaledAutoSingleLayerTest, UnsignaledNotAppliedWhenThereAreSignaled_UnsignaledFirst) { const sp<IBinder> kApplyToken1 = const sp<IBinder> kApplyToken1 = IInterface::asBinder(TransactionCompletedListener::getIInstance()); IInterface::asBinder(TransactionCompletedListener::getIInstance()); const sp<IBinder> kApplyToken2 = sp<BBinder>::make(); const sp<IBinder> kApplyToken2 = sp<BBinder>::make(); const sp<IBinder> kApplyToken3 = sp<BBinder>::make(); const auto kLayerId1 = 1; const auto kLayerId1 = 1; const auto kLayerId2 = 2; const auto kLayerId2 = 2; const auto kExpectedTransactionsApplied = 1u; const auto kExpectedTransactionsApplied = 2u; const auto kExpectedTransactionsPending = 1u; const auto unsignaledTransaction = createTransactionInfo(kApplyToken1, { createComposerState(kLayerId1, fence(Fence::Status::Unsignaled), layer_state_t::eBufferChanged), }); const auto signaledTransaction = createTransactionInfo(kApplyToken2, { createComposerState(kLayerId2, fence(Fence::Status::Signaled), layer_state_t::eBufferChanged), }); const auto signaledTransaction2 = createTransactionInfo(kApplyToken3, { createComposerState(kLayerId2, fence(Fence::Status::Signaled), layer_state_t::eBufferChanged), }); setTransactionStates({unsignaledTransaction, signaledTransaction, signaledTransaction2}, kExpectedTransactionsApplied, kExpectedTransactionsPending); } TEST_F(LatchUnsignaledAutoSingleLayerTest, UnsignaledNotAppliedWhenThereAreSignaled_SignaledFirst) { const sp<IBinder> kApplyToken1 = IInterface::asBinder(TransactionCompletedListener::getIInstance()); const sp<IBinder> kApplyToken2 = sp<BBinder>::make(); const sp<IBinder> kApplyToken3 = sp<BBinder>::make(); const auto kLayerId1 = 1; const auto kLayerId2 = 2; const auto kExpectedTransactionsApplied = 2u; const auto kExpectedTransactionsPending = 1u; const auto kExpectedTransactionsPending = 1u; const auto signaledTransaction = const auto signaledTransaction = Loading @@ -567,15 +606,23 @@ TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemoveSignaledWithUnsignaledInt fence(Fence::Status::Signaled), fence(Fence::Status::Signaled), layer_state_t::eBufferChanged), layer_state_t::eBufferChanged), }); }); const auto unsignaledTransaction = const auto signaledTransaction2 = createTransactionInfo(kApplyToken2, createTransactionInfo(kApplyToken2, { createComposerState(kLayerId1, fence(Fence::Status::Signaled), layer_state_t::eBufferChanged), }); const auto unsignaledTransaction = createTransactionInfo(kApplyToken3, { { createComposerState(kLayerId2, createComposerState(kLayerId2, fence(Fence::Status::Unsignaled), fence(Fence::Status::Unsignaled), layer_state_t::eBufferChanged), layer_state_t::eBufferChanged), }); }); setTransactionStates({signaledTransaction, unsignaledTransaction}, kExpectedTransactionsApplied, kExpectedTransactionsPending); setTransactionStates({signaledTransaction, signaledTransaction2, unsignaledTransaction}, kExpectedTransactionsApplied, kExpectedTransactionsPending); } } TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) { TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) { Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +72 −56 Original line number Original line Diff line number Diff line Loading @@ -3647,19 +3647,11 @@ bool SurfaceFlinger::stopTransactionProcessing( return false; return false; } } bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { void SurfaceFlinger::flushPendingTransactionQueues( // to prevent onHandleDestroyed from being called while the lock is held, std::vector<TransactionState>& transactions, // we must keep a copy of the transactions (specifically the composer std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, // states) around outside the scope of the lock std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions, std::vector<TransactionState> transactions; bool tryApplyUnsignaled) { // Layer handles that have transactions with buffers that are ready to be applied. std::unordered_set<sp<IBinder>, SpHash<IBinder>> bufferLayersReadyToPresent; std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions; { Mutex::Autolock _l(mStateLock); { Mutex::Autolock _l(mQueueLock); // Collect transactions from pending transaction queue. auto it = mPendingTransactionQueues.begin(); auto it = mPendingTransactionQueues.begin(); while (it != mPendingTransactionQueues.end()) { while (it != mPendingTransactionQueues.end()) { auto& [applyToken, transactionQueue] = *it; auto& [applyToken, transactionQueue] = *it; Loading @@ -3675,8 +3667,8 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { transaction.isAutoTimestamp, transaction.isAutoTimestamp, transaction.desiredPresentTime, transaction.desiredPresentTime, transaction.originUid, transaction.states, transaction.originUid, transaction.states, bufferLayersReadyToPresent, bufferLayersReadyToPresent, transactions.size(), transactions.size()); tryApplyUnsignaled); ATRACE_INT("TransactionReadiness", static_cast<int>(ready)); ATRACE_INT("TransactionReadiness", static_cast<int>(ready)); if (ready == TransactionReadiness::NotReady) { if (ready == TransactionReadiness::NotReady) { setTransactionFlags(eTransactionFlushNeeded); setTransactionFlags(eTransactionFlushNeeded); Loading @@ -3701,21 +3693,39 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { it = std::next(it, 1); it = std::next(it, 1); } } } } } bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { // 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>, SpHash<IBinder>> bufferLayersReadyToPresent; std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions; { Mutex::Autolock _l(mStateLock); { Mutex::Autolock _l(mQueueLock); // First collect transactions from the pending transaction queues. // We are not allowing unsignaled buffers here as we want to // collect all the transactions from applyTokens that are ready first. flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent, applyTokensWithUnsignaledTransactions, /*tryApplyUnsignaled*/ false); // Collect transactions from current transaction queue or queue to pending transactions. // Second, collect transactions from the transaction queue. // Case 1: push to pending when transactionIsReadyToBeApplied is false // Here as well we are not allowing unsignaled buffers for the same // or the first transaction was unsignaled. // reason as above. // Case 2: push to pending when there exist a pending queue. // Case 3: others are the transactions that are ready to apply. while (!mTransactionQueue.empty()) { while (!mTransactionQueue.empty()) { auto& transaction = mTransactionQueue.front(); auto& transaction = mTransactionQueue.front(); const bool pendingTransactions = const bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) != mPendingTransactionQueues.find(transaction.applyToken) != mPendingTransactionQueues.end(); mPendingTransactionQueues.end(); const auto ready = [&]() REQUIRES(mStateLock) { const auto ready = [&]() REQUIRES(mStateLock) { if (pendingTransactions || if (pendingTransactions) { stopTransactionProcessing(applyTokensWithUnsignaledTransactions)) { ATRACE_NAME("pendingTransactions"); ATRACE_NAME("pendingTransactions || stopTransactionProcessing"); return TransactionReadiness::NotReady; return TransactionReadiness::NotReady; } } Loading @@ -3724,7 +3734,8 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { transaction.desiredPresentTime, transaction.desiredPresentTime, transaction.originUid, transaction.states, transaction.originUid, transaction.states, bufferLayersReadyToPresent, bufferLayersReadyToPresent, transactions.size()); transactions.size(), /*tryApplyUnsignaled*/ false); }(); }(); ATRACE_INT("TransactionReadiness", static_cast<int>(ready)); ATRACE_INT("TransactionReadiness", static_cast<int>(ready)); if (ready == TransactionReadiness::NotReady) { if (ready == TransactionReadiness::NotReady) { Loading @@ -3733,16 +3744,21 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { transaction.traverseStatesWithBuffers([&](const layer_state_t& state) { transaction.traverseStatesWithBuffers([&](const layer_state_t& state) { bufferLayersReadyToPresent.insert(state.surface); bufferLayersReadyToPresent.insert(state.surface); }); }); const bool appliedUnsignaled = (ready == TransactionReadiness::ReadyUnsignaled); if (appliedUnsignaled) { applyTokensWithUnsignaledTransactions.insert(transaction.applyToken); } transactions.emplace_back(std::move(transaction)); transactions.emplace_back(std::move(transaction)); } } mTransactionQueue.pop_front(); mTransactionQueue.pop_front(); ATRACE_INT("TransactionQueue", mTransactionQueue.size()); ATRACE_INT("TransactionQueue", mTransactionQueue.size()); } } // We collected all transactions that could apply without latching unsignaled buffers. // If we are allowing latch unsignaled of some form, now it's the time to go over the // transactions that were not applied and try to apply them unsignaled. if (enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) { flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent, applyTokensWithUnsignaledTransactions, /*tryApplyUnsignaled*/ true); } return applyTransactions(transactions, vsyncId); return applyTransactions(transactions, vsyncId); } } } } Loading Loading @@ -3850,7 +3866,7 @@ auto SurfaceFlinger::transactionIsReadyToBeApplied( const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, uid_t originUid, const Vector<ComposerState>& states, uid_t originUid, const Vector<ComposerState>& states, const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, size_t totalTXapplied) const -> TransactionReadiness { size_t totalTXapplied, bool tryApplyUnsignaled) const -> TransactionReadiness { ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId); ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId); const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); // Do not present if the desiredPresentTime has not passed unless it is more than one second // Do not present if the desiredPresentTime has not passed unless it is more than one second Loading Loading @@ -3887,7 +3903,7 @@ auto SurfaceFlinger::transactionIsReadyToBeApplied( continue; continue; } } const bool allowLatchUnsignaled = const bool allowLatchUnsignaled = tryApplyUnsignaled && shouldLatchUnsignaled(layer, s, states.size(), totalTXapplied); shouldLatchUnsignaled(layer, s, states.size(), totalTXapplied); ATRACE_FORMAT("%s allowLatchUnsignaled=%s", layer->getName().c_str(), ATRACE_FORMAT("%s allowLatchUnsignaled=%s", layer->getName().c_str(), allowLatchUnsignaled ? "true" : "false"); allowLatchUnsignaled ? "true" : "false"); Loading
services/surfaceflinger/SurfaceFlinger.h +7 −1 Original line number Original line Diff line number Diff line Loading @@ -750,6 +750,12 @@ private: // Returns true if there is at least one transaction that needs to be flushed // Returns true if there is at least one transaction that needs to be flushed bool transactionFlushNeeded(); bool transactionFlushNeeded(); void flushPendingTransactionQueues( std::vector<TransactionState>& transactions, std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions, bool tryApplyUnsignaled) REQUIRES(mStateLock, mQueueLock); uint32_t setClientStateLocked(const FrameTimelineInfo&, ComposerState&, uint32_t setClientStateLocked(const FrameTimelineInfo&, ComposerState&, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, uint32_t permissions) REQUIRES(mStateLock); int64_t postTime, uint32_t permissions) REQUIRES(mStateLock); Loading Loading @@ -780,7 +786,7 @@ private: const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, uid_t originUid, const Vector<ComposerState>& states, uid_t originUid, const Vector<ComposerState>& states, const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent, size_t totalTXapplied) const REQUIRES(mStateLock); size_t totalTXapplied, bool tryApplyUnsignaled) const REQUIRES(mStateLock); static LatchUnsignaledConfig getLatchUnsignaledConfig(); static LatchUnsignaledConfig getLatchUnsignaledConfig(); bool shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t&, size_t numStates, bool shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t&, size_t numStates, size_t totalTXapplied) const; size_t totalTXapplied) const; Loading
services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +52 −5 Original line number Original line Diff line number Diff line Loading @@ -551,13 +551,52 @@ TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSignaledFromTheQueue) { kExpectedTransactionsPending); kExpectedTransactionsPending); } } TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemoveSignaledWithUnsignaledIntact) { TEST_F(LatchUnsignaledAutoSingleLayerTest, UnsignaledNotAppliedWhenThereAreSignaled_UnsignaledFirst) { const sp<IBinder> kApplyToken1 = const sp<IBinder> kApplyToken1 = IInterface::asBinder(TransactionCompletedListener::getIInstance()); IInterface::asBinder(TransactionCompletedListener::getIInstance()); const sp<IBinder> kApplyToken2 = sp<BBinder>::make(); const sp<IBinder> kApplyToken2 = sp<BBinder>::make(); const sp<IBinder> kApplyToken3 = sp<BBinder>::make(); const auto kLayerId1 = 1; const auto kLayerId1 = 1; const auto kLayerId2 = 2; const auto kLayerId2 = 2; const auto kExpectedTransactionsApplied = 1u; const auto kExpectedTransactionsApplied = 2u; const auto kExpectedTransactionsPending = 1u; const auto unsignaledTransaction = createTransactionInfo(kApplyToken1, { createComposerState(kLayerId1, fence(Fence::Status::Unsignaled), layer_state_t::eBufferChanged), }); const auto signaledTransaction = createTransactionInfo(kApplyToken2, { createComposerState(kLayerId2, fence(Fence::Status::Signaled), layer_state_t::eBufferChanged), }); const auto signaledTransaction2 = createTransactionInfo(kApplyToken3, { createComposerState(kLayerId2, fence(Fence::Status::Signaled), layer_state_t::eBufferChanged), }); setTransactionStates({unsignaledTransaction, signaledTransaction, signaledTransaction2}, kExpectedTransactionsApplied, kExpectedTransactionsPending); } TEST_F(LatchUnsignaledAutoSingleLayerTest, UnsignaledNotAppliedWhenThereAreSignaled_SignaledFirst) { const sp<IBinder> kApplyToken1 = IInterface::asBinder(TransactionCompletedListener::getIInstance()); const sp<IBinder> kApplyToken2 = sp<BBinder>::make(); const sp<IBinder> kApplyToken3 = sp<BBinder>::make(); const auto kLayerId1 = 1; const auto kLayerId2 = 2; const auto kExpectedTransactionsApplied = 2u; const auto kExpectedTransactionsPending = 1u; const auto kExpectedTransactionsPending = 1u; const auto signaledTransaction = const auto signaledTransaction = Loading @@ -567,15 +606,23 @@ TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemoveSignaledWithUnsignaledInt fence(Fence::Status::Signaled), fence(Fence::Status::Signaled), layer_state_t::eBufferChanged), layer_state_t::eBufferChanged), }); }); const auto unsignaledTransaction = const auto signaledTransaction2 = createTransactionInfo(kApplyToken2, createTransactionInfo(kApplyToken2, { createComposerState(kLayerId1, fence(Fence::Status::Signaled), layer_state_t::eBufferChanged), }); const auto unsignaledTransaction = createTransactionInfo(kApplyToken3, { { createComposerState(kLayerId2, createComposerState(kLayerId2, fence(Fence::Status::Unsignaled), fence(Fence::Status::Unsignaled), layer_state_t::eBufferChanged), layer_state_t::eBufferChanged), }); }); setTransactionStates({signaledTransaction, unsignaledTransaction}, kExpectedTransactionsApplied, kExpectedTransactionsPending); setTransactionStates({signaledTransaction, signaledTransaction2, unsignaledTransaction}, kExpectedTransactionsApplied, kExpectedTransactionsPending); } } TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) { TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) { Loading