Modify SurfaceView to use SurfaceFlinger child surfaces.

Here we have SurfaceView bypass the WindowManager and speak
directly to SurfaceFlinger using child surfaces. We also
implement some logic in the WM to handle child surfaces
in various Surface replacement scenarios.

For those following along in the revert Saga, this
also includes the follow up CLs to the original CL.
- Surface inset calculation
- Animation fixes.

The error causing the revert was an incorrect JNI signature
around deferTransactionUntilSurface. I've noted it inline.

Bug: 28858420
Bug: 31518219
Bug: 34888808
Bug: 35588318
Bug: 35396882
Test: Existing tests still pass (except for the ones that don't and will be deleted).
Change-Id: Ie56b6f7ab16f32d7fc459b8eba26594337ad55de
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 647adbf..4aa013a 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -785,6 +785,16 @@
         if (canFreezeBounds()) {
             freezeBounds();
         }
+
+        // In the process of tearing down before relaunching, the app will
+        // try and clean up it's child surfaces. We need to prevent this from
+        // happening, so we sever the children, transfering their ownership
+        // from the client it-self to the parent surface (owned by us).
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.mWinAnimator.detachChildren();
+        }
+
         mPendingRelaunchCount++;
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8b62236..66ec8f0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2199,6 +2199,15 @@
         if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
             mAccessibilityController.onWindowTransitionLocked(win, transit);
         }
+
+        // When we start the exit animation we take the Surface from the client
+        // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger
+        // side child surfaces, so they will remain preserved in their current state
+        // (rather than be cleaned up immediately by the app code).
+        SurfaceControl.openTransaction();
+        winAnimator.detachChildren();
+        SurfaceControl.closeTransaction();
+
         return focusMayChange;
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 6d572d7..4806068 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1532,6 +1532,13 @@
             return changed;
         }
 
+        // Next up we will notify the client that it's visibility has changed.
+        // We need to prevent it from destroying child surfaces until
+        // the animation has finished.
+        if (!visible && isVisibleNow()) {
+            mWinAnimator.detachChildren();
+        }
+
         if (visible != isVisibleNow()) {
             if (!runningAppAnimation) {
                 final AccessibilityController accessibilityController =
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 98598e1..4b71338 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -566,6 +566,20 @@
         if (!mDestroyPreservedSurfaceUponRedraw) {
             return;
         }
+        if (mSurfaceController != null) {
+            if (mPendingDestroySurface != null) {
+                // If we are preserving a surface but we aren't relaunching that means
+                // we are just doing an in-place switch. In that case any SurfaceFlinger side
+                // child layers need to be reparented to the new surface to make this
+                // transparent to the app.
+                if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
+                    SurfaceControl.openTransaction();
+                    mPendingDestroySurface.reparentChildrenInTransaction(mSurfaceController);
+                    SurfaceControl.closeTransaction();
+                }
+            }
+        }
+
         destroyDeferredSurfaceLocked();
         mDestroyPreservedSurfaceUponRedraw = false;
     }
@@ -1965,4 +1979,10 @@
         }
         return mForceScaleUntilResize;
     }
+
+    void detachChildren() {
+        if (mSurfaceController != null) {
+            mSurfaceController.detachChildren();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index f8e7428..f7d3343 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -135,6 +135,20 @@
         }
     }
 
+    void reparentChildrenInTransaction(WindowSurfaceController other) {
+        if (SHOW_TRANSACTIONS) Slog.i(TAG, "REPARENT from: " + this + " to: " + other);
+        if ((mSurfaceControl != null) && (other.mSurfaceControl != null)) {
+            mSurfaceControl.reparentChildren(other.getHandle());
+        }
+    }
+
+    void detachChildren() {
+        if (SHOW_TRANSACTIONS) Slog.i(TAG, "SEVER CHILDREN");
+        if (mSurfaceControl != null) {
+            mSurfaceControl.detachChildren();
+        }
+    }
+
     void hideInTransaction(String reason) {
         if (SHOW_TRANSACTIONS) logSurface("HIDE ( " + reason + " )", null);
         mHiddenForOtherReasons = true;