Dropping SurfaceFrames from Drawing State
Our assumption is that a buffer committed into drawing state will be
latched and presented. Based on this assumption, we present a
BufferSurfaceFrame only at latch time instead of commit time. However,
during back to back invalidates, there is a chance that the first
committed buffer is not latched. It could be replaced by another buffer
in the second invalidate. This leads to the SurfaceFrame getting stuck
in the pending classification list. To prevent this, have a check in
commitTransaction that drops the SurfaceFrame properly if it hasn't been
presented before.
Back to back invalidate can currently be triggered by just flashing a
clean build and launching the dialer.
Bug: 182214053
Test: libsurfaceflinger_unittest
Change-Id: I6cd9c4cbfb2ca50b96654ed240664758dad86f19
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4e52662..38e9b65 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1058,6 +1058,15 @@
}
void Layer::commitTransaction(State& stateToCommit) {
+ if (auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX;
+ mDrawingState.buffer != stateToCommit.buffer && bufferSurfaceFrame != nullptr &&
+ bufferSurfaceFrame->getPresentState() != PresentState::Presented) {
+ // If the previous buffer was committed but not latched (refreshPending - happens during
+ // back to back invalidates), it gets silently dropped here. Mark the corresponding
+ // SurfaceFrame as dropped to prevent it from getting stuck in the pending classification
+ // list.
+ addSurfaceFrameDroppedForBuffer(bufferSurfaceFrame);
+ }
mDrawingState = stateToCommit;
// Set the present state for all bufferlessSurfaceFramesTX to Presented. The