Stack APPLICATION_MEDIA_OVERLAY windows with relative layering.

See accompanying frameworks/native commit
 "SurfaceFlinger: Add parent-less relative layering" for a full explanation.

Test: Manual of bug repro steps. Plus tests for new SurfaceControl functionality included in frameworks/native.
Bug: 36693738
Change-Id: Ic54598117c1f44a206d33f03d0cc463fbef43fcc
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 1cb563f..3b15456 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -55,6 +55,8 @@
     private static native void nativeSetAnimationTransaction();
 
     private static native void nativeSetLayer(long nativeObject, int zorder);
+    private static native void nativeSetRelativeLayer(long nativeObject, IBinder relativeTo,
+            int zorder);
     private static native void nativeSetPosition(long nativeObject, float x, float y);
     private static native void nativeSetGeometryAppliesWithResize(long nativeObject);
     private static native void nativeSetSize(long nativeObject, int w, int h);
@@ -461,6 +463,11 @@
         nativeSetLayer(mNativeObject, zorder);
     }
 
+    public void setRelativeLayer(IBinder relativeTo, int zorder) {
+        checkNotReleased();
+        nativeSetRelativeLayer(mNativeObject, relativeTo, zorder);
+    }
+
     public void setPosition(float x, float y) {
         checkNotReleased();
         nativeSetPosition(mNativeObject, x, y);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index dc365b4..8b82314 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -289,6 +289,14 @@
     }
 }
 
+static void nativeSetRelativeLayer(JNIEnv* env, jclass clazz, jlong nativeObject,
+        jobject relativeTo, jint zorder) {
+    auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    sp<IBinder> handle = ibinderForJavaObject(env, relativeTo);
+
+    ctrl->setRelativeLayer(handle, zorder);
+}
+
 static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) {
     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
     status_t err = ctrl->setPosition(x, y);
@@ -774,6 +782,8 @@
             (void*)nativeSetAnimationTransaction },
     {"nativeSetLayer", "(JI)V",
             (void*)nativeSetLayer },
+    {"nativeSetRelativeLayer", "(JLandroid/os/IBinder;I)V",
+            (void*)nativeSetRelativeLayer },
     {"nativeSetPosition", "(JFF)V",
             (void*)nativeSetPosition },
     {"nativeSetGeometryAppliesWithResize", "(J)V",
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8098eea..979af7e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -50,6 +50,7 @@
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -4411,4 +4412,14 @@
             nowGone = true;
         }
     }
+
+    boolean usesRelativeZOrdering() {
+        if (!isChildWindow()) {
+            return false;
+        } else if (mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) {
+            return true;
+        } else {
+            return false;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a7f6db1..ae17d08 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -714,7 +714,16 @@
         }
 
         // Start a new transaction and apply position & offset.
-        mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, getLayerStack(), mAnimLayer);
+
+        mService.openSurfaceTransaction();
+        try {
+            mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, false);
+            mSurfaceController.setLayerStackInTransaction(getLayerStack());
+            mSurfaceController.setLayer(mAnimLayer);
+        } finally {
+            mService.closeSurfaceTransaction();
+        }
+
         mLastHidden = true;
 
         if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
@@ -1521,12 +1530,13 @@
                     + "," + mDsDy + "*" + w.mVScale + "]", false);
 
             boolean prepared =
-                mSurfaceController.prepareToShowInTransaction(mShownAlpha, mAnimLayer,
+                mSurfaceController.prepareToShowInTransaction(mShownAlpha,
                         mDsDx * w.mHScale * mExtraHScale,
                         mDtDx * w.mVScale * mExtraVScale,
                         mDtDy * w.mHScale * mExtraHScale,
                         mDsDy * w.mVScale * mExtraVScale,
                         recoveringMemory);
+            mSurfaceController.setLayer(mAnimLayer);
 
             if (prepared && mLastHidden && mDrawState == HAS_DRAWN) {
                 if (showSurfaceRobustlyLocked()) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index adf4501..edbdf8b 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -163,32 +163,6 @@
         }
     }
 
-    void setPositionAndLayer(float left, float top, int layerStack, int layer) {
-        mService.openSurfaceTransaction();
-        try {
-            mSurfaceX = left;
-            mSurfaceY = top;
-
-            try {
-                if (SHOW_TRANSACTIONS) logSurface(
-                        "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null);
-                mSurfaceControl.setPosition(left, top);
-                mSurfaceControl.setLayerStack(layerStack);
-
-                mSurfaceControl.setLayer(layer);
-                mSurfaceControl.setAlpha(0);
-                setShown(false);
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Error creating surface in " + this, e);
-                mAnimator.reclaimSomeSurfaceMemory("create-init", true);
-            }
-        } finally {
-            mService.closeSurfaceTransaction();
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-                    "<<< CLOSE TRANSACTION setPositionAndLayer");
-        }
-    }
-
     void destroyInTransaction() {
         if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
             Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
@@ -269,7 +243,15 @@
         if (mSurfaceControl != null) {
             mService.openSurfaceTransaction();
             try {
-                mSurfaceControl.setLayer(layer);
+                if (mAnimator.mWin.usesRelativeZOrdering()) {
+                    mSurfaceControl.setRelativeLayer(
+                            mAnimator.mWin.getParentWindow()
+                            .mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(),
+                            -1);
+                } else {
+                    mSurfaceLayer = layer;
+                    mSurfaceControl.setLayer(layer);
+                }
             } finally {
                 mService.closeSurfaceTransaction();
             }
@@ -363,15 +345,13 @@
         return false;
     }
 
-    boolean prepareToShowInTransaction(float alpha, int layer,
+    boolean prepareToShowInTransaction(float alpha,
             float dsdx, float dtdx, float dsdy,
             float dtdy, boolean recoveringMemory) {
         if (mSurfaceControl != null) {
             try {
                 mSurfaceAlpha = alpha;
                 mSurfaceControl.setAlpha(alpha);
-                mSurfaceLayer = layer;
-                mSurfaceControl.setLayer(layer);
                 mLastDsdx = dsdx;
                 mLastDtdx = dtdx;
                 mLastDsdy = dsdy;