summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorCraig Mautner <cmautner@google.com>2013-06-03 17:24:21 -0700
committerCraig Mautner <cmautner@google.com>2013-06-06 07:32:13 -0700
commit05eb730ca42eec3a40f916062af7442218135303 (patch)
tree0b960c4135c7ffce733e5048f2ebddbdd191fd87 /core/java
parent0efd4f0215f1df1207b67240d7a52b1da6af43c8 (diff)
Delay removal of windows from WindowManager
When relaunching activities the window manager clears out all windows by calling a ViewRootImpl.die() in a deferred fashion. Then it immediately deletes the ViewRootImpl and its view from its list of windows. When the die() is eventually executed it calls dispatchDetachedFromWindow() which tries to remove the previously removed windows causing an Exception to be thrown. This change waits to remove the windows until after die() has been completed. Fixes bug 8253030. Change-Id: I5b41be1c6b776e32128c064267653db98bd95292
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/view/ViewRootImpl.java1
-rw-r--r--core/java/android/view/WindowManagerGlobal.java54
2 files changed, 30 insertions, 25 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bcc58a27e2ff..62e0d3dada03 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5153,6 +5153,7 @@ public final class ViewRootImpl implements ViewParent,
mAdded = false;
}
+ WindowManagerGlobal.getInstance().doRemoveView(this);
}
public void requestUpdateConfiguration(Configuration config) {
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 0ff46e966288..fb0ee5912f3b 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -22,7 +22,6 @@ import android.content.ComponentCallbacks2;
import android.content.res.Configuration;
import android.opengl.ManagedEGLContext;
import android.os.IBinder;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -306,7 +305,8 @@ public final class WindowManagerGlobal {
synchronized (mLock) {
int index = findViewLocked(view, true);
- View curView = removeViewLocked(index, immediate);
+ View curView = mRoots[index].getView();
+ removeViewLocked(index, immediate);
if (curView == view) {
return;
}
@@ -323,7 +323,7 @@ public final class WindowManagerGlobal {
int count = mViews.length;
//Log.i("foo", "Closing all windows of " + token);
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
//Log.i("foo", "@ " + i + " token " + mParams[i].token
// + " view " + mRoots[i].getView());
if (token == null || mParams[i].token == token) {
@@ -335,18 +335,16 @@ public final class WindowManagerGlobal {
what + " " + who + " has leaked window "
+ root.getView() + " that was originally added here");
leak.setStackTrace(root.getLocation().getStackTrace());
- Log.e(TAG, leak.getMessage(), leak);
+ Log.e(TAG, "", leak);
}
removeViewLocked(i, false);
- i--;
- count--;
}
}
}
}
- private View removeViewLocked(int index, boolean immediate) {
+ private void removeViewLocked(int index, boolean immediate) {
ViewRootImpl root = mRoots[index];
View view = root.getView();
@@ -357,29 +355,35 @@ public final class WindowManagerGlobal {
}
}
root.die(immediate);
+ }
- final int count = mViews.length;
+ void doRemoveView(ViewRootImpl root) {
+ synchronized (mLock) {
+ final View view = root.getView();
+ if (view != null) {
+ view.assignParent(null);
+ }
- // remove it from the list
- View[] tmpViews = new View[count-1];
- removeItem(tmpViews, mViews, index);
- mViews = tmpViews;
+ final int newCount = mViews.length - 1;
+ for (int index = newCount; index >= 0; --index) {
+ if (mRoots[index] == root) {
+ // remove it from the list
+ View[] tmpViews = new View[newCount];
+ removeItem(tmpViews, mViews, index);
+ mViews = tmpViews;
- ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
- removeItem(tmpRoots, mRoots, index);
- mRoots = tmpRoots;
+ ViewRootImpl[] tmpRoots = new ViewRootImpl[newCount];
+ removeItem(tmpRoots, mRoots, index);
+ mRoots = tmpRoots;
- WindowManager.LayoutParams[] tmpParams
- = new WindowManager.LayoutParams[count-1];
- removeItem(tmpParams, mParams, index);
- mParams = tmpParams;
+ WindowManager.LayoutParams[] tmpParams = new WindowManager.LayoutParams[newCount];
+ removeItem(tmpParams, mParams, index);
+ mParams = tmpParams;
- if (view != null) {
- view.assignParent(null);
- // func doesn't allow null... does it matter if we clear them?
- //view.setLayoutParams(null);
+ return;
+ }
+ }
}
- return view;
}
private static void removeItem(Object[] dst, Object[] src, int index) {
@@ -403,7 +407,7 @@ public final class WindowManagerGlobal {
}
}
if (required) {
- throw new IllegalArgumentException("View not attached to window manager");
+ throw new IllegalArgumentException("View=" + view + " not attached to window manager");
}
return -1;
}