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

Commit 571771c3 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Added WindowContainer.removeImmediately to support immediate removal

There are 2 types of window conatiner removals. The ones that happen
immediately and the ones that are deferred until the system is in
a good state to handle them. WindowContainer and its child classes
now support both through WC.removeImmediately() and WC.removeIfPossible()
methods.
The method names create a consistency in the codebase and also makes is
obvious what the methods will do.

Bug: 30060889
Change-Id: I459c2eef17e20cefc42e9cc542c9a3c69fc9b898
parent 8fcf291c
Loading
Loading
Loading
Loading
+7 −11
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ class AppWindowToken extends WindowToken {
    final boolean voiceInteraction;

    Task mTask;
    // TODO: Have a fillParent variable in WindowContainer to this?
    boolean appFullscreen;
    int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    boolean layoutConfigChanges;
@@ -100,7 +101,7 @@ class AppWindowToken extends WindowToken {
    // These are to track the app's real drawing status if there were no saved surfaces.
    boolean allDrawnExcludingSaved;
    int numInterestingWindowsExcludingSaved;
    int numDrawnWindowsExclusingSaved;
    int numDrawnWindowsExcludingSaved;

    // Is this window's surface needed?  This is almost like hidden, except
    // it will sometimes be true a little earlier: when the token has
@@ -133,6 +134,7 @@ class AppWindowToken extends WindowToken {
    // Input application handle used by the input dispatcher.
    final InputApplicationHandle mInputApplicationHandle;

    // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
    boolean mIsExiting;

    boolean mLaunchTaskBehind;
@@ -356,18 +358,12 @@ class AppWindowToken extends WindowToken {
        return StackId.canReceiveKeys(mTask.mStack.mStackId) || mAlwaysFocusable;
    }

    void removeAppFromTaskLocked() {
    @Override
    void removeIfPossible() {
        mIsExiting = false;
        removeAllWindows();

        // Use local variable because removeAppToken will null out mTask.
        final Task task = mTask;
        if (task != null) {
            if (!task.removeAppToken(this)) {
                Slog.e(TAG, "removeAppFromTaskLocked: token=" + this
                        + " not found.");
            }
            task.mStack.mExitingAppTokens.remove(this);
        if (mTask != null) {
            mTask.detachChild(this);
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -514,7 +514,7 @@ class DisplayContent {
                    for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
                        AppWindowToken wtoken = tokens.get(tokenNdx);
                        if (wtoken.mIsExiting) {
                            wtoken.removeAppFromTaskLocked();
                            wtoken.removeIfPossible();
                        }
                    }
                }
+8 −0
Original line number Diff line number Diff line
@@ -179,6 +179,14 @@ class Task implements DimLayer.DimLayerUser {
        }
    }

    // TODO: Don't forget to switch to WC.detachChild
    void detachChild(AppWindowToken wtoken) {
        if (!removeAppToken(wtoken)) {
            Slog.e(TAG, "detachChild: token=" + this + " not found.");
        }
        mStack.mExitingAppTokens.remove(wtoken);
    }

    boolean removeAppToken(AppWindowToken wtoken) {
        boolean removed = mAppTokens.remove(wtoken);
        if (mAppTokens.size() == 0) {
+39 −6
Original line number Diff line number Diff line
@@ -67,17 +67,50 @@ class WindowContainer {
        mChildren.add(child);
    }

    /** Removes this window container and its children */
    /**
     * Removes this window container and its children with no regard for what else might be going on
     * in the system. For example, the container will be removed during animation if this method is
     * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
     * which allows the system to defer removal until a suitable time.
     */
    @CallSuper
    void remove() {
    void removeImmediately() {
        while (!mChildren.isEmpty()) {
            final WindowContainer child = mChildren.removeLast();
            child.remove();
            final WindowContainer child = mChildren.peekLast();
            child.removeImmediately();
            // Need to do this after calling remove on the child because the child might try to
            // remove/detach itself from its parent which will cause an exception if we remove
            // it before calling remove on the child.
            mChildren.remove(child);
        }

        if (mParent != null) {
            mParent.mChildren.remove(this);
            mParent = null;
            mParent.detachChild(this);
        }
    }

    /**
     * Removes this window container and its children taking care not to remove them during a
     * critical stage in the system. For example, some containers will not be removed during
     * animation if this method is called.
     */
    // TODO: figure-out implementation that works best for this.
    // E.g. when do we remove from parent list? maybe not...
    void removeIfPossible() {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer wc = mChildren.get(i);
            wc.removeIfPossible();
        }
    }

    /** Detaches the input child container from this container which is its parent. */
    @CallSuper
    void detachChild(WindowContainer child) {
        if (mChildren.remove(child)) {
            child.mParent = null;
        } else {
            throw new IllegalArgumentException("detachChild: container=" + child
                    + " is not a child of container=" + this);
        }
    }

+6 −4
Original line number Diff line number Diff line
@@ -247,7 +247,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;

/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
@@ -1896,7 +1895,10 @@ public class WindowManagerService extends IWindowManager.Stub

    /**
     * Performs some centralized bookkeeping clean-up on the window that is being removed.
     * NOTE: Should only be called from {@link WindowState#remove()}
     * NOTE: Should only be called from {@link WindowState#removeImmediately()}
     * TODO: Maybe better handled with a method {@link WindowContainer#detachChild} if we can
     * figure-out a good way to have all parents of a WindowState doing the same thing without
     * forgetting to add the wiring when a new parent of WindowState is added.
     */
    void postWindowRemoveCleanupLocked(WindowState win) {
        if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win);
@@ -3756,7 +3758,7 @@ public class WindowManagerService extends IWindowManager.Stub
                    // soon as their animations are complete
                    wtoken.mAppAnimator.clearAnimation();
                    wtoken.mAppAnimator.animating = false;
                    wtoken.removeAppFromTaskLocked();
                    wtoken.removeIfPossible();
                }

                wtoken.removed = true;
@@ -10449,7 +10451,7 @@ public class WindowManagerService extends IWindowManager.Stub
        public void removeWindowToken(IBinder token, boolean removeWindows) {
            synchronized(mWindowMap) {
                if (removeWindows) {
                    WindowToken wtoken = mTokenMap.remove(token);
                    final WindowToken wtoken = mTokenMap.remove(token);
                    if (wtoken != null) {
                        wtoken.removeAllWindows();
                    }
Loading