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/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index ade62bf..d314942 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -68,7 +68,7 @@
ALOGE("Found stale hardware composer layers when destroying "
"surface flinger layer %s",
mName.string());
- destroyAllHwcLayers();
+ destroyAllHwcLayersPlusChildren();
}
mTimeStats.onDestroy(getSequence());
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 038bc58..92a77b0 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -123,7 +123,7 @@
mFrameTracker.logAndResetStats(mName);
- destroyAllHwcLayers();
+ destroyAllHwcLayersPlusChildren();
mFlinger->onLayerDestroyed();
}
@@ -175,6 +175,14 @@
}
}
+void Layer::addToCurrentState() {
+ mRemovedFromCurrentState = false;
+
+ for (const auto& child : mCurrentChildren) {
+ child->addToCurrentState();
+ }
+}
+
// ---------------------------------------------------------------------------
// set-up
// ---------------------------------------------------------------------------
@@ -226,17 +234,21 @@
return true;
}
-void Layer::destroyAllHwcLayers() {
+void Layer::destroyHwcLayersForAllDisplays() {
size_t numLayers = getBE().mHwcLayers.size();
for (size_t i = 0; i < numLayers; ++i) {
LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed");
destroyHwcLayer(getBE().mHwcLayers.begin()->first);
}
+}
+
+void Layer::destroyAllHwcLayersPlusChildren() {
+ destroyHwcLayersForAllDisplays();
LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(),
"All hardware composer layers should have been destroyed");
for (const sp<Layer>& child : mDrawingChildren) {
- child->destroyAllHwcLayers();
+ child->destroyAllHwcLayersPlusChildren();
}
}
@@ -1587,6 +1599,10 @@
}
newParent->addChild(this);
+ if (!newParent->isRemovedFromCurrentState()) {
+ addToCurrentState();
+ }
+
sp<Client> client(mClientRef.promote());
sp<Client> newParentClient(newParent->mClientRef.promote());
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 40ebe1e..2e19b8b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -485,6 +485,11 @@
*/
void onRemovedFromCurrentState();
+ /*
+ * Called when the layer is added back to the current state list.
+ */
+ void addToCurrentState();
+
// Updates the transform hint in our SurfaceFlingerConsumer to match
// the current orientation of the display device.
void updateTransformHint(const sp<const DisplayDevice>& display) const;
@@ -506,7 +511,8 @@
bool createHwcLayer(HWComposer* hwc, DisplayId displayId);
bool destroyHwcLayer(DisplayId displayId);
- void destroyAllHwcLayers();
+ void destroyHwcLayersForAllDisplays();
+ void destroyAllHwcLayersPlusChildren();
bool hasHwcLayer(DisplayId displayId) const { return getBE().mHwcLayers.count(displayId) > 0; }
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);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8b389bc..d42536c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -547,6 +547,7 @@
// Can only be called from the main thread or with mStateLock held
uint32_t setTransactionFlags(uint32_t flags);
uint32_t setTransactionFlags(uint32_t flags, Scheduler::TransactionStart transactionStart);
+ void latchAndReleaseBuffer(const sp<Layer>& layer);
void commitTransaction();
bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
uint32_t setClientStateLocked(const ComposerState& composerState);