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) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f7b82e4..f94833b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -241,6 +241,7 @@
     bool setOverrideScalingMode(int32_t overrideScalingMode);
     void setInfo(uint32_t type, uint32_t appId);
     bool reparentChildren(const sp<IBinder>& layer);
+    bool reparentChild(const sp<IBinder>& newParentHandle, const sp<IBinder>& childHandle);
     bool detachChildren();
 
     // If we have received a new buffer this frame, we will pass its surface
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6a01f30..4b079d6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3103,6 +3103,13 @@
             // We don't trigger a traversal here because if no other state is
             // changed, we don't want this to cause any more work
         }
+        // Always re-parent the children that explicitly requested to get
+        // re-parented before the general re-parent of all children.
+        if (what & layer_state_t::eReparentChild) {
+            if (layer->reparentChild(s.parentHandleForChild, s.childHandle)) {
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
+        }
         if (what & layer_state_t::eReparentChildren) {
             if (layer->reparentChildren(s.reparentHandle)) {
                 flags |= eTransactionNeeded|eTraversalNeeded;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index a92e1f9..71aa52d 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -2679,6 +2679,13 @@
             // We don't trigger a traversal here because if no other state is
             // changed, we don't want this to cause any more work
         }
+        // Always re-parent the children that explicitly requested to get
+        // re-parented before the general re-parent of all children.
+        if (what & layer_state_t::eReparentChild) {
+            if (layer->reparentChild(s.parentHandleForChild, s.childHandle)) {
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
+        }
         if (what & layer_state_t::eReparentChildren) {
             if (layer->reparentChildren(s.reparentHandle)) {
                 flags |= eTransactionNeeded|eTraversalNeeded;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 4ce14f8..aef5a5f 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1123,4 +1123,33 @@
     fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
 }
 
+TEST_F(ChildLayerTest, ReparentChild) {
+    SurfaceComposerClient::openGlobalTransaction();
+    mChild->show();
+    mChild->setPosition(10, 10);
+    mFGSurfaceControl->setPosition(64, 64);
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // Top left of foreground must now be visible
+        mCapture->expectFGColor(64, 64);
+        // But 10 pixels in we should see the child surface
+        mCapture->expectChildColor(74, 74);
+        // And 10 more pixels we should be back to the foreground surface
+        mCapture->expectFGColor(84, 84);
+    }
+    mFGSurfaceControl->reparentChild(mBGSurfaceControl->getHandle(), mChild->getHandle());
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->expectFGColor(64, 64);
+        // In reparenting we should have exposed the entire foreground surface.
+        mCapture->expectFGColor(74, 74);
+        // And the child layer should now begin at 10, 10 (since the BG
+        // layer is at (0, 0)).
+        mCapture->expectBGColor(9, 9);
+        mCapture->expectChildColor(10, 10);
+    }
+}
+
 }