Add a re-parent function to re-parent a specific child.
This is similar to reparentChildren, but the reparentChild will
only re-parent a specific child to the new parent and not all
children.
Test: Added test in Transaction_test for reparentChild.
Change-Id: I4275e0d5f1d5601b489956753c78a56d1a5d4c1c
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index e92565f..c406f74 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2625,6 +2625,44 @@
return true;
}
+bool Layer::reparentChild(const sp<IBinder>& newParentHandle, const sp<IBinder>& childHandle) {
+ if (newParentHandle == nullptr || childHandle == nullptr) {
+ return false;
+ }
+
+ auto handle = static_cast<Handle*>(newParentHandle.get());
+ sp<Layer> newParent = handle->owner.promote();
+ if (newParent == nullptr) {
+ ALOGE("Unable to promote Layer handle");
+ return false;
+ }
+
+ handle = static_cast<Handle*>(childHandle.get());
+ sp<Layer> child = handle->owner.promote();
+ if (child == nullptr) {
+ ALOGE("Unable to promote child Layer handle");
+ return false;
+ }
+
+ if (mCurrentChildren.indexOf(child) < 0) {
+ ALOGE("Child layer is not child of current layer");
+ return false;
+ }
+
+ sp<Client> parentClient(mClientRef.promote());
+ sp<Client> childClient(child->mClientRef.promote());
+ sp<Client> newParentClient(newParent->mClientRef.promote());
+
+ if (parentClient != childClient || childClient != newParentClient) {
+ ALOGE("Current layer, child layer, and new parent layer must have the same client");
+ return false;
+ }
+
+ newParent->addChild(child);
+ mCurrentChildren.remove(child);
+ return true;
+}
+
bool Layer::detachChildren() {
traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* child) {
if (child == this) {