Clear unexpected buffer handle of sideband layer
If the buffer handle is not cleared after MediaCodec disconnected
and the surface is re-used for another sideband stream. SurfaceFlinger
would trigger incorrect composition type change from sideband to
device when SurfaceView layout changed.
Clear the buffer if the layer was about to set a new sideband
handle.
Bug: 291202822
Test: Adjust the screen layout after played 2 different sideband
stream. No composition type change.
Change-Id: I0b42d68ea03fb09db9aefc257d6071e559a3d8d2
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9a5173b..047d376 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -3092,6 +3092,32 @@
return true;
}
+void Layer::releasePreviousBuffer() {
+ mReleasePreviousBuffer = true;
+ if (!mBufferInfo.mBuffer ||
+ (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
+ mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
+ // If mDrawingState has a buffer, and we are about to update again
+ // before swapping to drawing state, then the first buffer will be
+ // dropped and we should decrement the pending buffer count and
+ // call any release buffer callbacks if set.
+ callReleaseBufferCallback(mDrawingState.releaseBufferListener,
+ mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
+ mDrawingState.acquireFence);
+ decrementPendingBufferCount();
+ if (mDrawingState.bufferSurfaceFrameTX != nullptr &&
+ mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) {
+ addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX, systemTime());
+ mDrawingState.bufferSurfaceFrameTX.reset();
+ }
+ } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) {
+ callReleaseBufferCallback(mDrawingState.releaseBufferListener,
+ mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
+ mLastClientCompositionFence);
+ mLastClientCompositionFence = nullptr;
+ }
+}
+
void Layer::resetDrawingStateBufferInfo() {
mDrawingState.producerId = 0;
mDrawingState.frameNumber = 0;
@@ -3116,29 +3142,7 @@
ATRACE_FORMAT_INSTANT("setBuffer %s - %" PRIu64, getDebugName(), frameNumber);
if (mDrawingState.buffer) {
- mReleasePreviousBuffer = true;
- if (!mBufferInfo.mBuffer ||
- (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
- mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
- // If mDrawingState has a buffer, and we are about to update again
- // before swapping to drawing state, then the first buffer will be
- // dropped and we should decrement the pending buffer count and
- // call any release buffer callbacks if set.
- callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
- mDrawingState.acquireFence);
- decrementPendingBufferCount();
- if (mDrawingState.bufferSurfaceFrameTX != nullptr &&
- mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) {
- addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX, systemTime());
- mDrawingState.bufferSurfaceFrameTX.reset();
- }
- } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) {
- callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
- mLastClientCompositionFence);
- mLastClientCompositionFence = nullptr;
- }
+ releasePreviousBuffer();
} else if (buffer) {
// if we are latching a buffer for the first time then clear the mLastLatchTime since
// we don't want to incorrectly classify a frame if we miss the desired present time.
@@ -3156,6 +3160,12 @@
mDrawingState.bufferSurfaceFrameTX = nullptr;
setFrameTimelineVsyncForBufferlessTransaction(info, postTime);
return true;
+ } else {
+ // release sideband stream if it exists and a non null buffer is being set
+ if (mDrawingState.sidebandStream != nullptr) {
+ mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
+ mDrawingState.sidebandStream = nullptr;
+ }
}
if ((mDrawingState.producerId > bufferData.producerId) ||
@@ -3344,7 +3354,8 @@
return true;
}
-bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
+bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream, const FrameTimelineInfo& info,
+ nsecs_t postTime) {
if (mDrawingState.sidebandStream == sidebandStream) return false;
if (mDrawingState.sidebandStream != nullptr && sidebandStream == nullptr) {
@@ -3355,6 +3366,12 @@
mDrawingState.sidebandStream = sidebandStream;
mDrawingState.modified = true;
+ if (sidebandStream != nullptr && mDrawingState.buffer != nullptr) {
+ releasePreviousBuffer();
+ resetDrawingStateBufferInfo();
+ mDrawingState.bufferSurfaceFrameTX = nullptr;
+ setFrameTimelineVsyncForBufferlessTransaction(info, postTime);
+ }
setTransactionFlags(eTransactionNeeded);
if (!mSidebandStreamChanged.exchange(true)) {
// mSidebandStreamChanged was false
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index dc4ceb0..0b0cef5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -317,7 +317,8 @@
bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/);
bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/);
bool setApi(int32_t /*api*/);
- bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/);
+ bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/,
+ const FrameTimelineInfo& /* info*/, nsecs_t /* postTime */);
bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& /*handles*/,
bool willPresent);
virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace)
@@ -1204,6 +1205,7 @@
half4 mBorderColor;
void setTransformHintLegacy(ui::Transform::RotationFlags);
+ void releasePreviousBuffer();
void resetDrawingStateBufferInfo();
// Transform hint provided to the producer. This must be accessed holding
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 517dc96..4adcd55 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5139,7 +5139,8 @@
if (layer->setApi(s.api)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eSidebandStreamChanged) {
- if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded;
+ if (layer->setSidebandStream(s.sidebandStream, frameTimelineInfo, postTime))
+ flags |= eTraversalNeeded;
}
if (what & layer_state_t::eInputInfoChanged) {
layer->setInputInfo(*s.windowInfoHandle->getInfo());
@@ -5383,7 +5384,8 @@
if (layer->setCrop(s.crop)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eSidebandStreamChanged) {
- if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded;
+ if (layer->setSidebandStream(s.sidebandStream, frameTimelineInfo, postTime))
+ flags |= eTraversalNeeded;
}
if (what & layer_state_t::eDataspaceChanged) {
if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded;
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
index 9f0bdde..39a7ee5 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
@@ -153,7 +153,8 @@
native_handle_t* testHandle = native_handle_create(0, 1);
const bool ownsHandle = mFdp.ConsumeBool();
sp<NativeHandle> nativeHandle = sp<NativeHandle>::make(testHandle, ownsHandle);
- layer->setSidebandStream(nativeHandle);
+ layer->setSidebandStream(nativeHandle, getFuzzedFrameTimelineInfo(),
+ mFdp.ConsumeIntegral<nsecs_t>() /* postTime */);
layer->computeSourceBounds(getFuzzedFloatRect(&mFdp));
layer->fenceHasSignaled();
diff --git a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
index 108151e..1cf14ae 100644
--- a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
@@ -127,7 +127,7 @@
sp<NativeHandle> stream =
NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
false);
- layer->setSidebandStream(stream);
+ layer->setSidebandStream(stream, FrameTimelineInfo{}, 20);
mFlinger.mutableCurrentState().layersSortedByZ.add(layer);
mTunnelModeEnabledReporter->updateTunnelModeStatus();
mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener);
@@ -151,7 +151,7 @@
sp<NativeHandle> stream =
NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
false);
- layerWithSidebandStream->setSidebandStream(stream);
+ layerWithSidebandStream->setSidebandStream(stream, FrameTimelineInfo{}, 20);
mFlinger.mutableCurrentState().layersSortedByZ.add(simpleLayer);
mFlinger.mutableCurrentState().layersSortedByZ.add(layerWithSidebandStream);