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 "