SurfaceFlinger: Ensure relatives are not detached with children.

A misapplication of traverseInZOrder...unfortunately we will have to watch
out for this. This code was also mistakenly accessing mDrawingState.

Test: Transaction_test.cpp
Change-Id: I6aa51885f52edff89f1ed5512408bf0a5a227af5
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 80987a4..22a72f2 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1661,17 +1661,14 @@
 }
 
 bool Layer::detachChildren() {
-    traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* child) {
-        if (child == this) {
-            return;
-        }
-
+    for (const sp<Layer>& child : mCurrentChildren) {
         sp<Client> parentClient = mClientRef.promote();
         sp<Client> client(child->mClientRef.promote());
         if (client != nullptr && parentClient != client) {
-            client->detachLayer(child);
+            client->detachLayer(child.get());
+            child->detachChildren();
         }
-    });
+    }
 
     return true;
 }
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 16a16a5..57a55fd 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -258,6 +258,43 @@
     sp<SurfaceControl> mSyncSurfaceControl;
 };
 
+TEST_F(LayerUpdateTest, RelativesAreNotDetached) {
+    sp<ScreenCapture> sc;
+
+    sp<SurfaceControl> relative = mComposerClient->createSurface(
+            String8("relativeTestSurface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0);
+    fillSurfaceRGBA8(relative, 10, 10, 10);
+    waitForPostedBuffers();
+
+    Transaction{}.setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1)
+            .setPosition(relative, 64, 64)
+            .apply();
+
+    {
+        // The relative should be on top of the FG control.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(64, 64, 10, 10, 10);
+    }
+    Transaction{}.detachChildren(mFGSurfaceControl)
+            .apply();
+
+    {
+        // Nothing should change at this point.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(64, 64, 10, 10, 10);
+    }
+
+    Transaction{}.hide(relative)
+            .apply();
+
+    {
+        // Ensure that the relative was actually hidden, rather than
+        // being left in the detached but visible state.
+        ScreenCapture::captureScreen(&sc);
+        sc->expectFGColor(64, 64);
+    }
+}
+
 TEST_F(LayerUpdateTest, LayerMoveWorks) {
     sp<ScreenCapture> sc;
     {