Fixes for parentless layers
1. When a layer is removed, it needs to latch a buffer before the buffer
can be released.
2. If a layer is removed from current state, it needs to get re-added
back to current state when it gets reparented to a layer that is not
removed from current state
3. If a layer is added as a child to a layer that has been removed from
current state, the layer adding needs to succeed, but the layer needs to
be automatically set as removed from current state.
Bug: 111297488
Test: Test with updated ActivityView that has a SurfaceControl that has
no reference in SF tree
Change-Id: I8b723666964c61aaf7119b60ac256d19f85732b0
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 35ba391..43899e0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2717,6 +2717,17 @@
}
}
+void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) {
+ if (layer->hasReadyFrame()) {
+ const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+ if (layer->shouldPresentNow(expectedPresentTime)) {
+ bool ignored = false;
+ layer->latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
+ }
+ }
+ layer->releasePendingBuffer(systemTime());
+}
+
void SurfaceFlinger::commitTransaction()
{
if (!mLayersPendingRemoval.isEmpty()) {
@@ -2730,11 +2741,9 @@
// showing at its last configured state until we eventually
// abandon the buffer queue.
if (l->isRemovedFromCurrentState()) {
- l->destroyAllHwcLayers();
- // destroyAllHwcLayers traverses to children, but releasePendingBuffer
- // doesn't in other scenarios. So we have to traverse explicitly here.
l->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* child) {
- child->releasePendingBuffer(systemTime());
+ child->destroyHwcLayersForAllDisplays();
+ latchAndReleaseBuffer(child);
});
}
}
@@ -3171,7 +3180,7 @@
} else {
if (parent->isRemovedFromCurrentState()) {
ALOGE("addClientLayer called with a removed parent");
- return NAME_NOT_FOUND;
+ lbc->onRemovedFromCurrentState();
}
parent->addChild(lbc);
}