surfaceflinger: fix layer count
When a layer is removed, mLayerCount is always decremented by 1 even
though the layer has children. This commit fixes that by making
sure mLayerCount is properly decremented, and makes sure that a
parent layer must be a valid layer in mCurrentState.
Bug: 37121786
Test: manually open and close Camera app
Change-Id: I5a3e18be41646b167b4d361dfe08db4d06e1c2d0
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7392006..317c4cc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2659,8 +2659,13 @@
if (parent == nullptr) {
mCurrentState.layersSortedByZ.add(lbc);
} else {
+ if (mCurrentState.layersSortedByZ.indexOf(parent) < 0) {
+ ALOGE("addClientLayer called with a removed parent");
+ return NAME_NOT_FOUND;
+ }
parent->addChild(lbc);
}
+
mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
mLayersAdded = true;
mNumLayers++;
@@ -2679,6 +2684,17 @@
const ssize_t index = (p != nullptr) ? p->removeChild(layer) :
mCurrentState.layersSortedByZ.remove(layer);
+ if (p != nullptr) {
+ sp<Layer> ancestor = p;
+ while (ancestor->getParent() != nullptr) {
+ ancestor = ancestor->getParent();
+ }
+ if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
+ ALOGE("removeLayer called with a layer whose parent has been removed");
+ return NAME_NOT_FOUND;
+ }
+ }
+
// As a matter of normal operation, the LayerCleaner will produce a second
// attempt to remove the surface. The Layer will be kept alive in mDrawingState
// so we will succeed in promoting it, but it's already been removed
@@ -2695,7 +2711,7 @@
mLayersPendingRemoval.add(layer);
mLayersRemoved = true;
- mNumLayers--;
+ mNumLayers -= 1 + layer->getChildrenCount();
setTransactionFlags(eTransactionNeeded);
return NO_ERROR;
}