Handle null buffer when calling Transaction::setBuffer
When Transaction::setBuffer is called with a null buffer, we release the
old buffer and unset the eBufferChange flag
Test: SurfaceControlTest
Test: ReleaseBufferCallbackTest#SetBuffer_OverwriteBuffersWithNull
Fixes: 233252754
Change-Id: I5cde94916655f82d146bd9d66c170b71db983966
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 501f8cf..47d801a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1497,6 +1497,13 @@
releaseBufferIfOverwriting(*s);
+ if (buffer == nullptr) {
+ s->what &= ~layer_state_t::eBufferChanged;
+ s->bufferData = nullptr;
+ mContainsBuffer = false;
+ return *this;
+ }
+
std::shared_ptr<BufferData> bufferData = std::make_shared<BufferData>();
bufferData->buffer = buffer;
uint64_t frameNumber = sc->resolveFrameNumber(optFrameNumber);
diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
index 027a15e..a6d7f58 100644
--- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
+++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
@@ -465,4 +465,22 @@
ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
}
+TEST_F(ReleaseBufferCallbackTest, SetBuffer_OverwriteBuffersWithNull) {
+ sp<SurfaceControl> layer = createBufferStateLayer();
+ ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
+
+ sp<GraphicBuffer> firstBuffer = getBuffer();
+ ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
+
+ // Create transaction with a buffer.
+ Transaction transaction;
+ transaction.setBuffer(layer, firstBuffer, std::nullopt, firstBufferCallbackId.framenumber,
+ releaseCallback->getCallback());
+
+ // Call setBuffer on the same transaction with a null buffer.
+ transaction.setBuffer(layer, nullptr, std::nullopt, 0, releaseCallback->getCallback());
+
+ ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
+}
+
} // namespace android