Allow relative layering of children

Initially we had hoped not to go down this route in order to produce the most
understandable model, but in the end it seems to be the most sane way to
satisfy some existing use cases from the WM. In particular we have the use
case of the IME. The IME may of course be larger than the application it is
targetting, in particular we see this in side by side split-screen portrait
and freeform. However, various UI features such as the text drag handles,
spell checking popups, etc, are controlled by the application process
and modelled as child windows of the application. This is a good fit for them
as they need to inherit most properties of the application window: Cropping,
Transform, Alpha. However they need to appear over the IME! As the IME can't
be a child of the application (it is bigger), we now see our use case for relative
layering. Perhaps the drag handles could be reimplemented as controlled by the IME
process but if nothing else as a legacy API we have exposed the idea of child windows
of the app going over the IME and are likely to need to continue to support it in some
mode.

Test: Transaction_test.cpp
Change-Id: If2d831bcbe88fc753b02c044a57882cca6ccffbb
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1237ee4..1085e74 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3107,11 +3107,21 @@
         }
     }
     if (what & layer_state_t::eRelativeLayerChanged) {
-        ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-        if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
-            mCurrentState.layersSortedByZ.removeAt(idx);
-            mCurrentState.layersSortedByZ.add(layer);
-            flags |= eTransactionNeeded|eTraversalNeeded;
+        // NOTE: index needs to be calculated before we update the state
+        const auto& p = layer->getParent();
+        if (p == nullptr) {
+            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+            if (layer->setRelativeLayer(s.relativeLayerHandle, s.z) && idx >= 0) {
+                mCurrentState.layersSortedByZ.removeAt(idx);
+                mCurrentState.layersSortedByZ.add(layer);
+                // we need traversal (state changed)
+                // AND transaction (list changed)
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
+        } else {
+            if (p->setChildRelativeLayer(layer, s.relativeLayerHandle, s.z)) {
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
         }
     }
     if (what & layer_state_t::eSizeChanged) {