Merge "Fix unsafe layer hierarchy access" into main
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index 2b20de3..39a6b77 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -260,27 +260,36 @@
hierarchy->mParent->updateChild(hierarchy, LayerHierarchy::Variant::Attached);
}
-void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) {
- if (root->mLayer) {
- attachToRelativeParent(root);
- }
- for (auto& [child, childVariant] : root->mChildren) {
- if (childVariant == LayerHierarchy::Variant::Detached ||
- childVariant == LayerHierarchy::Variant::Attached) {
- attachHierarchyToRelativeParent(child);
+std::vector<LayerHierarchy*> LayerHierarchyBuilder::getDescendants(LayerHierarchy* root) {
+ std::vector<LayerHierarchy*> hierarchies;
+ hierarchies.push_back(root);
+ std::vector<LayerHierarchy*> descendants;
+ for (size_t i = 0; i < hierarchies.size(); i++) {
+ LayerHierarchy* hierarchy = hierarchies[i];
+ if (hierarchy->mLayer) {
+ descendants.push_back(hierarchy);
}
+ for (auto& [child, childVariant] : hierarchy->mChildren) {
+ if (childVariant == LayerHierarchy::Variant::Detached ||
+ childVariant == LayerHierarchy::Variant::Attached) {
+ hierarchies.push_back(child);
+ }
+ }
+ }
+ return descendants;
+}
+
+void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) {
+ std::vector<LayerHierarchy*> hierarchiesToAttach = getDescendants(root);
+ for (LayerHierarchy* hierarchy : hierarchiesToAttach) {
+ attachToRelativeParent(hierarchy);
}
}
void LayerHierarchyBuilder::detachHierarchyFromRelativeParent(LayerHierarchy* root) {
- if (root->mLayer) {
- detachFromRelativeParent(root);
- }
- for (auto& [child, childVariant] : root->mChildren) {
- if (childVariant == LayerHierarchy::Variant::Detached ||
- childVariant == LayerHierarchy::Variant::Attached) {
- detachHierarchyFromRelativeParent(child);
- }
+ std::vector<LayerHierarchy*> hierarchiesToDetach = getDescendants(root);
+ for (LayerHierarchy* hierarchy : hierarchiesToDetach) {
+ detachFromRelativeParent(hierarchy);
}
}
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index 69710be..d023f9e 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -218,6 +218,7 @@
void detachFromParent(LayerHierarchy*);
void attachToRelativeParent(LayerHierarchy*);
void detachFromRelativeParent(LayerHierarchy*);
+ std::vector<LayerHierarchy*> getDescendants(LayerHierarchy*);
void attachHierarchyToRelativeParent(LayerHierarchy*);
void detachHierarchyFromRelativeParent(LayerHierarchy*);
void init(const std::vector<std::unique_ptr<RequestedLayerState>>&);