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

Commit 8f303ad9 authored by Craig Mautner's avatar Craig Mautner
Browse files

Complete doDie() before executing addView().

If WindowManager.addView() is called soon after
WindowManager.removeView() then the MSG_DIE in the ViewRootImpl
mHandler queue may not have had time to execute. This will cause
WindowManagerGlobal to throw an exception since the DecorView
is being added before it has been removed.

This fix detects that situation by saving all Views that are queued
up for ViewRootImpl.doDie(). If addView() is called for one of these
Views then doDie() is called immediately and not called when MSG_DIE
eventually makes its way through the queue.

This change also makes doDie() non-reentrant by only allowing it to
carry out its functions the first time it is called. This keeps
dispatchDetachedWindows() from causing destruction by recursively
calling back into doDie(). This is usually caused by calling
dismissDialog() from within dispatchDetachedWindow().

Fixes bug 9404689.
Fixes bug 9406261.

Change-Id: Id4fc8054e273215d82366428fef51b9ba98385fe
parent 5f73a7df
Loading
Loading
Loading
Loading
+29 −25
Original line number Diff line number Diff line
@@ -313,6 +313,9 @@ public final class ViewRootImpl implements ViewParent,

    private int mViewLayoutDirectionInitial;

    /** Set to true once doDie() has been called. */
    private boolean mRemoved;

    /**
     * Consistency verifier for debugging purposes.
     */
@@ -420,8 +423,6 @@ public final class ViewRootImpl implements ViewParent,
        synchronized (this) {
            if (mView == null) {
                mView = view;
                Slog.d(TAG, "setView: b9406261 setting mView to " + view + " mAdded=" + mAdded
                        + " Callers=" + Debug.getCallers(4));
                mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
                mFallbackEventHandler.setView(view);
                mWindowAttributes.copyFrom(attrs);
@@ -477,8 +478,6 @@ public final class ViewRootImpl implements ViewParent,
                            = panelParentView.getApplicationWindowToken();
                }
                mAdded = true;
                Slog.d(TAG, "setView: b9406261 setting mAdded=true mView=" + mView
                        + " Callers=" + Debug.getCallers(4));
                int res; /* = WindowManagerImpl.ADD_OKAY; */

                // Schedule the first layout -before- adding to the window
@@ -504,8 +503,6 @@ public final class ViewRootImpl implements ViewParent,
                    mFallbackEventHandler.setView(null);
                    unscheduleTraversals();
                    setAccessibilityFocus(null, null);
                    Slog.d(TAG, "setView: b9406261 threw exception e=" + e
                            + " Callers=" + Debug.getCallers(4));
                    throw new RuntimeException("Adding window failed", e);
                } finally {
                    if (restore) {
@@ -845,6 +842,7 @@ public final class ViewRootImpl implements ViewParent,
        invalidateChildInParent(null, dirty);
    }

    @Override
    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
        checkThread();
        if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);
@@ -902,10 +900,12 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    @Override
    public ViewParent getParent() {
        return null;
    }

    @Override
    public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
        if (child != mView) {
            throw new RuntimeException("child is not mine, honest!");
@@ -2805,9 +2805,7 @@ public final class ViewRootImpl implements ViewParent,

        setAccessibilityFocus(null, null);

        if (mView != null) {
        mView.assignParent(null);
        }
        mView = null;
        mAttachInfo.mRootView = null;
        mAttachInfo.mSurface = null;
@@ -5126,12 +5124,18 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    public void die(boolean immediate) {
    /**
     * @param immediate True, do now if not in traversal. False, put on queue and do later.
     * @return True, request has been queued. False, request has been completed.
     */
    boolean die(boolean immediate) {
        // Make sure we do execute immediately if we are in the middle of a traversal or the damage
        // done by dispatchDetachedFromWindow will cause havoc on return.
        if (immediate && !mIsInTraversal) {
            doDie();
        } else {
            return false;
        }

        if (!mIsDrawing) {
            destroyHardwareRenderer();
        } else {
@@ -5139,16 +5143,18 @@ public final class ViewRootImpl implements ViewParent,
                    "  window=" + this + ", title=" + mWindowAttributes.getTitle());
        }
        mHandler.sendEmptyMessage(MSG_DIE);
        }
        return true;
    }

    void doDie() {
        checkThread();
        if (LOCAL_LOGV) Log.v(TAG, "DIE in " + this + " of " + mSurface);
        synchronized (this) {
            if (mRemoved) {
                return;
            }
            mRemoved = true;
            if (mAdded) {
                Slog.d(TAG, "doDie: b9406261 mAdded==true mView=" + mView
                    + " Callers=" + Debug.getCallers(4));
                dispatchDetachedFromWindow();
            }

@@ -5176,8 +5182,6 @@ public final class ViewRootImpl implements ViewParent,
                }
            }

            Slog.d(TAG, "doDie: b9406261 setting mAdded=false mView=" + mView
                + " Callers=" + Debug.getCallers(4));
            mAdded = false;
        }
        WindowManagerGlobal.getInstance().doRemoveView(this);
+16 −4
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.util.AndroidRuntimeException;
import android.util.ArraySet;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;

@@ -111,6 +112,7 @@ public final class WindowManagerGlobal {
    private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
    private final ArrayList<WindowManager.LayoutParams> mParams =
            new ArrayList<WindowManager.LayoutParams>();
    private final ArraySet<View> mDyingViews = new ArraySet<View>();
    private boolean mNeedsEglTerminate;

    private Runnable mSystemPropertyUpdater;
@@ -220,9 +222,15 @@ public final class WindowManagerGlobal {

            int index = findViewLocked(view, false);
            if (index >= 0) {
                if (mDyingViews.contains(view)) {
                    // Don't wait for MSG_DIE to make it's way through root's queue.
                    mRoots.get(index).doDie();
                } else {
                    throw new IllegalStateException("View " + view
                            + " has already been added to the window manager.");
                }
                // The previous removeView() had not completed executing. Now it has.
            }

            // If this is a panel window, then find the window it is being
            // attached to for future reference.
@@ -334,9 +342,12 @@ public final class WindowManagerGlobal {
                imm.windowDismissed(mViews.get(index).getWindowToken());
            }
        }
        root.die(immediate);
        boolean deferred = root.die(immediate);
        if (view != null) {
            view.assignParent(null);
            if (deferred) {
                mDyingViews.add(view);
            }
        }
    }

@@ -345,8 +356,9 @@ public final class WindowManagerGlobal {
            final int index = mRoots.indexOf(root);
            if (index >= 0) {
                mRoots.remove(index);
                mViews.remove(index);
                mParams.remove(index);
                final View view = mViews.remove(index);
                mDyingViews.remove(view);
            }
        }
    }