diff options
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 71 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 9 | ||||
| -rw-r--r-- | services/surfaceflinger/TransactionCallbackInvoker.cpp | 11 | ||||
| -rw-r--r-- | services/surfaceflinger/TransactionCallbackInvoker.h | 10 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/LayerCallback_test.cpp | 56 |
5 files changed, 107 insertions, 50 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 88a1cba631..c039aa645b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2022,17 +2022,23 @@ bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expected bool SurfaceFlinger::flushAndCommitTransactions() { ATRACE_CALL(); + bool needsTraversal = false; if (clearTransactionFlags(eTransactionFlushNeeded)) { - flushTransactionQueues(); + needsTraversal = flushTransactionQueues(); } - const bool shouldCommit = (getTransactionFlags() & ~eTransactionFlushNeeded) || mForceTraversal; + const bool shouldCommit = (getTransactionFlags() & ~eTransactionFlushNeeded) || needsTraversal; if (shouldCommit) { commitTransactions(); } - // Invoke OnCommit callbacks. - mTransactionCallbackInvoker.sendCallbacks(); + if (!needsTraversal) { + // Invoke empty transaction callbacks early. + mTransactionCallbackInvoker.sendCallbacks(false /* onCommitOnly */); + } else { + // Invoke OnCommit callbacks. + mTransactionCallbackInvoker.sendCallbacks(true /* onCommitOnly */); + } if (transactionFlushNeeded()) { setTransactionFlags(eTransactionFlushNeeded); @@ -2329,7 +2335,7 @@ void SurfaceFlinger::postComposition() { mVisibleRegionsWereDirtyThisFrame = false; mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0].fence); - mTransactionCallbackInvoker.sendCallbacks(); + mTransactionCallbackInvoker.sendCallbacks(false /* onCommitOnly */); mTransactionCallbackInvoker.clearCompletedTransactions(); if (display && display->isInternal() && display->getPowerMode() == hal::PowerMode::ON && @@ -2942,7 +2948,6 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { processDisplayChangesLocked(); processDisplayHotplugEventsLocked(); } - mForceTraversal = false; mForceTransactionDisplayChange = displayTransactionNeeded; if (mSomeChildrenChanged) { @@ -3416,11 +3421,8 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule return old; } -void SurfaceFlinger::setTraversalNeeded() { - mForceTraversal = true; -} - -void SurfaceFlinger::flushTransactionQueues() { +bool SurfaceFlinger::flushTransactionQueues() { + bool needsTraversal = false; // 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 @@ -3489,19 +3491,23 @@ void SurfaceFlinger::flushTransactionQueues() { // Now apply all transactions. for (const 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); + needsTraversal |= + 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)); } } - } + } // unlock mStateLock + return needsTraversal; } bool SurfaceFlinger::transactionFlushNeeded() { @@ -3707,7 +3713,7 @@ status_t SurfaceFlinger::setTransactionState( return NO_ERROR; } -void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo, +bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states, const Vector<DisplayState>& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, @@ -3729,12 +3735,10 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin mTransactionCallbackInvoker.addEmptyTransaction(listener); } - std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> listenerCallbacksWithSurfaces; uint32_t clientStateFlags = 0; for (const ComposerState& state : states) { - clientStateFlags |= - setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp, - postTime, permissions, listenerCallbacksWithSurfaces); + clientStateFlags |= setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, + isAutoTimestamp, postTime, permissions); if ((flags & eAnimation) && state.state.surface) { if (const auto layer = fromHandle(state.state.surface).promote(); layer) { mScheduler->recordLayerHistory(layer.get(), @@ -3744,10 +3748,6 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin } } - // If the state doesn't require a traversal and there are callbacks, send them now - if (!(clientStateFlags & eTraversalNeeded) && hasListenerCallbacks) { - mTransactionCallbackInvoker.sendCallbacks(); - } transactionFlags |= clientStateFlags; if (permissions & Permission::ACCESS_SURFACE_FLINGER) { @@ -3769,6 +3769,7 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin transactionFlags = eTransactionNeeded; } + bool needsTraversal = false; if (transactionFlags) { if (mInterceptor->isEnabled()) { mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags, @@ -3779,7 +3780,7 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin // so we don't have to wake up again next frame to preform an unnecessary traversal. if (transactionFlags & eTraversalNeeded) { transactionFlags = transactionFlags & (~eTraversalNeeded); - mForceTraversal = true; + needsTraversal = true; } if (transactionFlags) { setTransactionFlags(transactionFlags); @@ -3789,6 +3790,8 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin mAnimTransactionPending = true; } } + + return needsTraversal; } uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) { @@ -3857,10 +3860,10 @@ bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermis return true; } -uint32_t SurfaceFlinger::setClientStateLocked( - const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState, - int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, uint32_t permissions, - std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& outListenerCallbacks) { +uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTimelineInfo, + const ComposerState& composerState, + int64_t desiredPresentTime, bool isAutoTimestamp, + int64_t postTime, uint32_t permissions) { const layer_state_t& s = composerState.state; const bool privileged = permissions & Permission::ACCESS_SURFACE_FLINGER; @@ -3874,13 +3877,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( ListenerCallbacks onCommitCallbacks = listener.filter(CallbackId::Type::ON_COMMIT); if (!onCommitCallbacks.callbackIds.empty()) { filteredListeners.push_back(onCommitCallbacks); - outListenerCallbacks.insert(onCommitCallbacks); } ListenerCallbacks onCompleteCallbacks = listener.filter(CallbackId::Type::ON_COMPLETE); if (!onCompleteCallbacks.callbackIds.empty()) { filteredListeners.push_back(onCompleteCallbacks); - outListenerCallbacks.insert(onCompleteCallbacks); } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c45eee1b32..c712061983 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -712,7 +712,7 @@ private: /* * Transactions */ - void applyTransactionState(const FrameTimelineInfo& info, const Vector<ComposerState>& state, + bool applyTransactionState(const FrameTimelineInfo& info, const Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, @@ -722,15 +722,13 @@ private: int originPid, int originUid, uint64_t transactionId) REQUIRES(mStateLock); // flush pending transaction that was presented after desiredPresentTime. - void flushTransactionQueues(); + bool flushTransactionQueues(); // Returns true if there is at least one transaction that needs to be flushed bool transactionFlushNeeded(); uint32_t setClientStateLocked(const FrameTimelineInfo&, const ComposerState&, int64_t desiredPresentTime, bool isAutoTimestamp, - int64_t postTime, uint32_t permissions, - std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>&) - REQUIRES(mStateLock); + int64_t postTime, uint32_t permissions) REQUIRES(mStateLock); uint32_t getTransactionFlags() const; @@ -1115,7 +1113,6 @@ private: std::vector<std::shared_ptr<CountDownLatch>> mTransactionCommittedSignals; bool mAnimTransactionPending = false; SortedVector<sp<Layer>> mLayersPendingRemoval; - bool mForceTraversal = false; // global color transform states Daltonizer mDaltonizer; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 8fbf0b4d07..f3d46ea061 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -121,7 +121,7 @@ status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle( return addCallbackHandle(handle, std::vector<JankData>()); } -status_t TransactionCallbackInvoker::findTransactionStats( +status_t TransactionCallbackInvoker::findOrCreateTransactionStats( const sp<IBinder>& listener, const std::vector<CallbackId>& callbackIds, TransactionStats** outTransactionStats) { auto& transactionStatsDeque = mCompletedTransactions[listener]; @@ -143,7 +143,8 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp<CallbackHandle>& // If we can't find the transaction stats something has gone wrong. The client should call // startRegistration before trying to add a callback handle. TransactionStats* transactionStats; - status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats); + status_t err = + findOrCreateTransactionStats(handle->listener, handle->callbackIds, &transactionStats); if (err != NO_ERROR) { return err; } @@ -204,7 +205,7 @@ void TransactionCallbackInvoker::addPresentFence(const sp<Fence>& presentFence) mPresentFence = presentFence; } -void TransactionCallbackInvoker::sendCallbacks() { +void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { // For each listener auto completedTransactionsItr = mCompletedTransactions.begin(); while (completedTransactionsItr != mCompletedTransactions.end()) { @@ -216,6 +217,10 @@ void TransactionCallbackInvoker::sendCallbacks() { auto transactionStatsItr = transactionStatsDeque.begin(); while (transactionStatsItr != transactionStatsDeque.end()) { auto& transactionStats = *transactionStatsItr; + if (onCommitOnly && !containsOnCommitCallbacks(transactionStats.callbackIds)) { + transactionStatsItr++; + continue; + } // If the transaction has been latched if (transactionStats.latchTime >= 0 && diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 100dbfa8aa..e203d41bd9 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -76,7 +76,7 @@ public: void addPresentFence(const sp<Fence>& presentFence); - void sendCallbacks(); + void sendCallbacks(bool onCommitOnly); void clearCompletedTransactions() { mCompletedTransactions.clear(); } @@ -86,11 +86,9 @@ public: private: - status_t findTransactionStats(const sp<IBinder>& listener, - const std::vector<CallbackId>& callbackIds, - TransactionStats** outTransactionStats); - - + status_t findOrCreateTransactionStats(const sp<IBinder>& listener, + const std::vector<CallbackId>& callbackIds, + TransactionStats** outTransactionStats); std::unordered_map<sp<IBinder>, std::deque<TransactionStats>, IListenerHash> mCompletedTransactions; diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 9ddbed21d8..91a5b528f8 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -1029,4 +1029,60 @@ TEST_F(LayerCallbackTest, ExpectedPresentTime) { EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); } +// b202394221 +TEST_F(LayerCallbackTest, EmptyBufferStateChanges) { + sp<SurfaceControl> bufferLayer, emptyBufferLayer; + ASSERT_NO_FATAL_FAILURE(bufferLayer = createBufferStateLayer()); + ASSERT_NO_FATAL_FAILURE(emptyBufferLayer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + for (size_t i = 0; i < 10; i++) { + int err = fillTransaction(transaction, &callback, bufferLayer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction, bufferLayer, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.setPosition(emptyBufferLayer, 1 + i, 2 + i); + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, bufferLayer, + ExpectedResult::Buffer::ACQUIRED, + (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED + : ExpectedResult::PreviousBuffer::RELEASED); + expected.addSurface(ExpectedResult::Transaction::PRESENTED, emptyBufferLayer, + ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::PreviousBuffer::NOT_RELEASED); + + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected)); + } + ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState()); +} + +// b202394221 +TEST_F(LayerCallbackTest, DISABLED_NonBufferLayerStateChanges) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createColorLayer("ColorLayer", Color::RED)); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + transaction.setPosition(layer, 1, 2); + transaction.apply(); + + ExpectedResult expected; + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + } // namespace android |