Merge "Close leaked windows when trying to preserve main one" into nyc-dev
am: 4ef107bb7a

* commit '4ef107bb7ad0c1f28db710374bb118e6658d3238':
  Close leaked windows when trying to preserve main one

Change-Id: Ie98ad06c08eb4486d98327201fb7fa10456a2459
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 43238ec..cfffe34 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4183,12 +4183,10 @@
                         // window is being added.
                         r.mPendingRemoveWindow = r.window;
                         r.mPendingRemoveWindowManager = wm;
-                        if (r.mPreserveWindow) {
-                            // We can only keep the part of the view hierarchy that we control,
-                            // everything else must be removed, because it might not be able to
-                            // behave properly when activity is relaunching.
-                            r.window.clearContentView();
-                        }
+                        // We can only keep the part of the view hierarchy that we control,
+                        // everything else must be removed, because it might not be able to
+                        // behave properly when activity is relaunching.
+                        r.window.clearContentView();
                     } else {
                         wm.removeViewImmediate(v);
                     }
@@ -4196,6 +4194,13 @@
                 if (wtoken != null && r.mPendingRemoveWindow == null) {
                     WindowManagerGlobal.getInstance().closeAll(wtoken,
                             r.activity.getClass().getName(), "Activity");
+                } else if (r.mPendingRemoveWindow != null) {
+                    // We're preserving only one window, others should be closed so app views
+                    // will be detached before the final tear down. It should be done now because
+                    // some components (e.g. WebView) rely on detach callbacks to perform receiver
+                    // unregister and other cleanup.
+                    WindowManagerGlobal.getInstance().closeAllExceptView(token, v,
+                            r.activity.getClass().getName(), "Activity");
                 }
                 r.activity.mDecor = null;
             }
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 887cc3a..11734d3 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -391,17 +391,34 @@
         }
     }
 
+    /**
+     * Remove all roots with specified token.
+     *
+     * @param token app or window token.
+     * @param who name of caller, used in logs.
+     * @param what type of caller, used in logs.
+     */
     public void closeAll(IBinder token, String who, String what) {
+        closeAllExceptView(token, null /* view */, who, what);
+    }
+
+    /**
+     * Remove all roots with specified token, except maybe one view.
+     *
+     * @param token app or window token.
+     * @param view view that should be should be preserved along with it's root.
+     *             Pass null if everything should be removed.
+     * @param who name of caller, used in logs.
+     * @param what type of caller, used in logs.
+     */
+    public void closeAllExceptView(IBinder token, View view, String who, String what) {
         synchronized (mLock) {
             int count = mViews.size();
-            //Log.i("foo", "Closing all windows of " + token);
             for (int i = 0; i < count; i++) {
-                //Log.i("foo", "@ " + i + " token " + mParams[i].token
-                //        + " view " + mRoots[i].getView());
-                if (token == null || mParams.get(i).token == token) {
+                if ((view == null || mViews.get(i) != view)
+                        && (token == null || mParams.get(i).token == token)) {
                     ViewRootImpl root = mRoots.get(i);
 
-                    //Log.i("foo", "Force closing " + root);
                     if (who != null) {
                         WindowLeaked leak = new WindowLeaked(
                                 what + " " + who + " has leaked window "