Preserve relative z layer info when moving layers offscreen
When a layer is removed from screen, by reparenting it to null, we need to
remove its relative z info as well. Otherwise, if the layer has a visible
relative parent, it will continue to be drawn.
However, there are some scenarios where it maybe useful to preserve relative z.
When a layer is temporarily moved offscreen, and the layer has children with
relative z ordered to other children, then the client logic can be made simpler
by preserving the relative z info for all the children and only removing relative
z info if its relative parent is not on the pending removal state.
Bug: 132613412
Test: atest SurfaceFlinger_test
Test: go/wm-smoke
Change-Id: Id9e2d164673c9028fb27a38ab2b3005269ad4932
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3ca6ef5..898f3bc 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -158,18 +158,26 @@
}
}
-void Layer::onRemovedFromCurrentState() {
- mRemovedFromCurrentState = true;
+void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) {
+ if (mCurrentState.zOrderRelativeOf == nullptr) {
+ return;
+ }
- // the layer is removed from SF mCurrentState to mLayersPendingRemoval
- if (mCurrentState.zOrderRelativeOf != nullptr) {
- sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
- if (strongRelative != nullptr) {
- strongRelative->removeZOrderRelative(this);
- mFlinger->setTransactionFlags(eTraversalNeeded);
- }
+ sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+ if (strongRelative == nullptr) {
+ setZOrderRelativeOf(nullptr);
+ return;
+ }
+
+ if (!std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) {
+ strongRelative->removeZOrderRelative(this);
+ mFlinger->setTransactionFlags(eTraversalNeeded);
setZOrderRelativeOf(nullptr);
}
+}
+
+void Layer::removeFromCurrentState() {
+ mRemovedFromCurrentState = true;
// Since we are no longer reachable from CurrentState SurfaceFlinger
// will no longer invoke doTransaction for us, and so we will
@@ -186,13 +194,18 @@
mLocalSyncPoints.clear();
}
- for (const auto& child : mCurrentChildren) {
- child->onRemovedFromCurrentState();
- }
-
mFlinger->markLayerPendingRemovalLocked(this);
}
+void Layer::onRemovedFromCurrentState() {
+ auto layersInTree = getLayersInTree(LayerVector::StateSet::Current);
+ std::sort(layersInTree.begin(), layersInTree.end());
+ for (const auto& layer : layersInTree) {
+ layer->removeFromCurrentState();
+ layer->removeRelativeZ(layersInTree);
+ }
+}
+
void Layer::addToCurrentState() {
mRemovedFromCurrentState = false;