Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 05eb730c authored by Craig Mautner's avatar Craig Mautner
Browse files

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
parent 0efd4f02
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5153,6 +5153,7 @@ public final class ViewRootImpl implements ViewParent,

            mAdded = false;
        }
        WindowManagerGlobal.getInstance().doRemoveView(this);
    }

    public void requestUpdateConfiguration(Configuration config) {
+29 −25
Original line number Diff line number Diff line
@@ -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;
            }
@@ -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);
            }

            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[count-1];
                    View[] tmpViews = new View[newCount];
                    removeItem(tmpViews, mViews, index);
                    mViews = tmpViews;

        ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
                    ViewRootImpl[] tmpRoots = new ViewRootImpl[newCount];
                    removeItem(tmpRoots, mRoots, index);
                    mRoots = tmpRoots;

        WindowManager.LayoutParams[] tmpParams
                = new WindowManager.LayoutParams[count-1];
                    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;
    }