diff options
| author | 2023-07-25 16:52:01 -0500 | |
|---|---|---|
| committer | 2023-07-25 18:30:40 -0500 | |
| commit | 30da367c6c0781d9783459567ec57d9d10c77c92 (patch) | |
| tree | c075cb15ef0e378afa4df00e5692598d4ef3e1cf | |
| parent | d3208d8ff6a1aeafb0bbb872aff46ba8d089f710 (diff) | |
Ensure transaction commit callbacks are called at most once.
Bug: 288781573
Bug: 292443283
Test: atest LayerTransactionTest
Change-Id: Ide66601b8a892b4bf5a331d83d38b4bd50919751
| -rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 6 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/LayerTransaction_test.cpp | 29 |
2 files changed, 34 insertions, 1 deletions
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 5bc05ef0d8..db99726739 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -377,7 +377,6 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener } auto& [callbackFunction, callbackSurfaceControls] = callbacksMap[callbackId]; if (!callbackFunction) { - ALOGE("cannot call null callback function, skipping"); continue; } std::vector<SurfaceControlStats> surfaceControlStats; @@ -394,6 +393,11 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener callbackFunction(transactionStats.latchTime, transactionStats.presentFence, surfaceControlStats); + + // More than one transaction may contain the same callback id. Erase the callback from + // the map to ensure that it is only called once. This can happen if transactions are + // parcelled out of process and applied in both processes. + callbacksMap.erase(callbackId); } // handle on complete callbacks diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp index cbd54e7aa9..03de8d0b6d 100644 --- a/services/surfaceflinger/tests/LayerTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp @@ -184,6 +184,35 @@ TEST_F(LayerTransactionTest, BufferTakesPriorityOverColor) { } } +TEST_F(LayerTransactionTest, CommitCallbackCalledOnce) { + auto callCount = 0; + auto commitCallback = + [&callCount](void* /* context */, nsecs_t /* latchTime */, + const sp<Fence>& /* presentFence */, + const std::vector<SurfaceControlStats>& /* stats */) mutable { + callCount++; + }; + + // Create two transactions that both contain the same callback id. + Transaction t1; + t1.addTransactionCommittedCallback(commitCallback, nullptr); + Parcel parcel; + t1.writeToParcel(&parcel); + parcel.setDataPosition(0); + Transaction t2; + t2.readFromParcel(&parcel); + + // Apply the two transactions. There is a race here as we can't guarantee that the two + // transactions will be applied within the same SurfaceFlinger commit. If the transactions are + // applied within the same commit then we verify that callback ids are deduplicated within a + // single commit. Otherwise, we verify that commit callbacks are deduplicated across separate + // commits. + t1.apply(); + t2.apply(/*synchronous=*/true); + + ASSERT_EQ(callCount, 1); +} + } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues |