Several fixes for saved surface

- Do not save if the exiting app is no longer top of task

- Mark saved surfaces as invalid when recoving memory, they will
  be reclaimed if they're hidden.

- Save surface when visibility changed to GONE

- Discard saved surface after rotation

- Misc minor fixes and clean-up

bug: 19940527

Change-Id: I5760c7a7b4bf37ef6bdd39cae793a97cf7579429
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 943e3ea..c5bd3a7 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -17,6 +17,9 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static com.android.server.wm.WindowManagerService.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerService.DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.WindowManagerService.TAG;
 
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.wm.WindowManagerService.H;
@@ -296,6 +299,52 @@
         }
     }
 
+    /**
+     * Checks whether we should save surfaces for this app.
+     *
+     * @return true if the surfaces should be saved, false otherwise.
+     */
+    boolean shouldSaveSurface() {
+        // We want to save surface if the app's windows are "allDrawn", or if we're
+        // currently animating with save surfaces. (If the app didn't even finish
+        // drawing when the user exits, but we have a saved surface from last time,
+        // we still want to keep that surface.)
+        mHasSavedSurface = allDrawn || mAnimatingWithSavedSurface;
+        if (mHasSavedSurface) {
+            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
+                    "Saving surface: " + this);
+            return true;
+        }
+        return false;
+    }
+
+    void restoreSavedSurfaces() {
+        if (!mHasSavedSurface) {
+            return;
+        }
+
+        if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
+                "Restoring saved surfaces: " + this + ", allDrawn=" + allDrawn);
+
+        mHasSavedSurface = false;
+        mAnimatingWithSavedSurface = true;
+        for (int i = windows.size() - 1; i >= 0; i--) {
+            WindowState ws = windows.get(i);
+            ws.mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
+        }
+    }
+
+    void destroySavedSurfaces() {
+        if (mHasSavedSurface) {
+            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
+                    "Destroying saved surface: " + this);
+            for (int i = windows.size() - 1; i >= 0; i--) {
+                final WindowState win = windows.get(i);
+                win.mWinAnimator.destroySurfaceLocked();
+            }
+        }
+    }
+
     @Override
     void removeAllWindows() {
         for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;