1c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner/*
2c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * Copyright (C) 2013 The Android Open Source Project
3c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner *
4c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * Licensed under the Apache License, Version 2.0 (the "License");
5c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * you may not use this file except in compliance with the License.
6c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * You may obtain a copy of the License at
7c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner *
8c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner *      http://www.apache.org/licenses/LICENSE-2.0
9c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner *
10c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * Unless required by applicable law or agreed to in writing, software
11c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * distributed under the License is distributed on an "AS IS" BASIS,
12c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * See the License for the specific language governing permissions and
14c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * limitations under the License.
15c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner */
16c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
17c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautnerpackage com.android.server.wm;
18c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
19c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautnerimport android.graphics.Rect;
20a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport android.util.Slog;
21c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
229e4f28cfa157fff89e42859edc9cce546508491fCraig Mautnerimport static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
23a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport static com.android.server.wm.WindowManagerService.DEBUG_STACK;
24a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautnerimport static com.android.server.wm.WindowManagerService.TAG;
259e4f28cfa157fff89e42859edc9cce546508491fCraig Mautner
2600af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautnerimport java.io.PrintWriter;
27d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner
28c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautnerpublic class StackBox {
295a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    /** Used with {@link WindowManagerService#createStack}. Dependent on Configuration LTR/RTL. */
3005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    public static final int TASK_STACK_GOES_BEFORE = 0;
315a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    /** Used with {@link WindowManagerService#createStack}. Dependent on Configuration LTR/RTL. */
32c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    public static final int TASK_STACK_GOES_AFTER = 1;
335a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    /** Used with {@link WindowManagerService#createStack}. Horizontal to left of. */
345a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    public static final int TASK_STACK_TO_LEFT_OF = 2;
355a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    /** Used with {@link WindowManagerService#createStack}. Horizontal to right of. */
365a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    public static final int TASK_STACK_TO_RIGHT_OF = 3;
37967212cb542e6eeb308678367b53381bff984c31Craig Mautner    /** Used with {@link WindowManagerService#createStack}. Vertical: lower t/b Rect values. */
385a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    public static final int TASK_STACK_GOES_ABOVE = 4;
39967212cb542e6eeb308678367b53381bff984c31Craig Mautner    /** Used with {@link WindowManagerService#createStack}. Vertical: higher t/b Rect values. */
405a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    public static final int TASK_STACK_GOES_BELOW = 5;
41967212cb542e6eeb308678367b53381bff984c31Craig Mautner    /** Used with {@link WindowManagerService#createStack}. Put on a higher layer on display. */
425a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    public static final int TASK_STACK_GOES_OVER = 6;
43967212cb542e6eeb308678367b53381bff984c31Craig Mautner    /** Used with {@link WindowManagerService#createStack}. Put on a lower layer on display. */
445a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    public static final int TASK_STACK_GOES_UNDER = 7;
45c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
465ff12101722874f5e7b0cadf06f4c53f4ec4b917Craig Mautner    static int sCurrentBoxId = 0;
475ff12101722874f5e7b0cadf06f4c53f4ec4b917Craig Mautner
485ff12101722874f5e7b0cadf06f4c53f4ec4b917Craig Mautner    /** Unique id for this box */
495ff12101722874f5e7b0cadf06f4c53f4ec4b917Craig Mautner    final int mStackBoxId;
505ff12101722874f5e7b0cadf06f4c53f4ec4b917Craig Mautner
5105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    /** The service */
5205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    final WindowManagerService mService;
5305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner
5400af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** The display this box sits in. */
55c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    final DisplayContent mDisplayContent;
5600af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
5700af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** Non-null indicates this is mFirst or mSecond of a parent StackBox. Null indicates this
5800af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     * is this entire size of mDisplayContent. */
594cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner    StackBox mParent;
6000af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
6100af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** First child, this is null exactly when mStack is non-null. */
62c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    StackBox mFirst;
6300af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
6400af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** Second child, this is null exactly when mStack is non-null. */
65c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    StackBox mSecond;
6600af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
6700af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** Stack of Tasks, this is null exactly when mFirst and mSecond are non-null. */
68c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    TaskStack mStack;
6900af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
7000af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** Content limits relative to the DisplayContent this sits in. */
71967212cb542e6eeb308678367b53381bff984c31Craig Mautner    Rect mBounds = new Rect();
7200af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
7300af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** Relative orientation of mFirst and mSecond. */
7400af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    boolean mVertical;
7500af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
76967212cb542e6eeb308678367b53381bff984c31Craig Mautner    /** Fraction of mBounds to devote to mFirst, remainder goes to mSecond */
77967212cb542e6eeb308678367b53381bff984c31Craig Mautner    float mWeight;
78967212cb542e6eeb308678367b53381bff984c31Craig Mautner
7900af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** Dirty flag. Something inside this or some descendant of this has changed. */
80c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    boolean layoutNeeded;
8100af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
82d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner    /** True if this StackBox sits below the Status Bar. */
83d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner    boolean mUnderStatusBar;
84d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner
85967212cb542e6eeb308678367b53381bff984c31Craig Mautner    /** Used to keep from reallocating a temporary Rect for propagating bounds to child boxes */
86967212cb542e6eeb308678367b53381bff984c31Craig Mautner    Rect mTmpRect = new Rect();
87967212cb542e6eeb308678367b53381bff984c31Craig Mautner
8805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    StackBox(WindowManagerService service, DisplayContent displayContent, StackBox parent) {
895ff12101722874f5e7b0cadf06f4c53f4ec4b917Craig Mautner        synchronized (StackBox.class) {
905ff12101722874f5e7b0cadf06f4c53f4ec4b917Craig Mautner            mStackBoxId = sCurrentBoxId++;
915ff12101722874f5e7b0cadf06f4c53f4ec4b917Craig Mautner        }
925ff12101722874f5e7b0cadf06f4c53f4ec4b917Craig Mautner
9305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        mService = service;
94c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        mDisplayContent = displayContent;
95967212cb542e6eeb308678367b53381bff984c31Craig Mautner        mParent = parent;
96c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    }
97c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
98c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    /** Propagate #layoutNeeded bottom up. */
99c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    void makeDirty() {
100c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        layoutNeeded = true;
101c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        if (mParent != null) {
102c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner            mParent.makeDirty();
103c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        }
104c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    }
105c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
10600af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /**
1075a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner     * Determine if a particular StackBox is this one or a descendant of this one.
1085a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner     * @param stackBoxId The StackBox being searched for.
1095a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner     * @return true if the specified StackBox matches this or one of its descendants.
11000af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     */
1115a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    boolean contains(int stackBoxId) {
112dc725fe93b05c38b47a967fdbbc003be915a2b76Craig Mautner        return mStackBoxId == stackBoxId ||
113dc725fe93b05c38b47a967fdbbc003be915a2b76Craig Mautner                (mStack == null &&  (mFirst.contains(stackBoxId) || mSecond.contains(stackBoxId)));
11400af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    }
11500af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
116cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner    /**
117cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner     * Return the stackId of the stack that intersects the passed point.
118cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner     * @param x coordinate of point.
119cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner     * @param y coordinate of point.
120cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner     * @return -1 if point is outside of mBounds, otherwise the stackId of the containing stack.
121cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner     */
122cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner    int stackIdFromPoint(int x, int y) {
123cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner        if (!mBounds.contains(x, y)) {
124cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner            return -1;
125cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner        }
126cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner        if (mStack != null) {
127cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner            return mStack.mStackId;
128cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner        }
129cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner        int stackId = mFirst.stackIdFromPoint(x, y);
130cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner        if (stackId >= 0) {
131cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner            return stackId;
132cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner        }
133cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner        return mSecond.stackIdFromPoint(x, y);
134cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner    }
135cf910b0c714b2ca90ea0013e5695850506a1d36fCraig Mautner
1364cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner    /** Determine if this StackBox is the first child or second child.
1374cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner     * @return true if this is the first child.
138967212cb542e6eeb308678367b53381bff984c31Craig Mautner     */
1394cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner    boolean isFirstChild() {
14005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        return mParent != null && mParent.mFirst == this;
141967212cb542e6eeb308678367b53381bff984c31Craig Mautner    }
142967212cb542e6eeb308678367b53381bff984c31Craig Mautner
143967212cb542e6eeb308678367b53381bff984c31Craig Mautner    /** Returns the bounds of the specified TaskStack if it is contained in this StackBox.
144967212cb542e6eeb308678367b53381bff984c31Craig Mautner     * @param stackId the TaskStack to find the bounds of.
145967212cb542e6eeb308678367b53381bff984c31Craig Mautner     * @return a new Rect with the bounds of stackId if it is within this StackBox, null otherwise.
146967212cb542e6eeb308678367b53381bff984c31Craig Mautner     */
147967212cb542e6eeb308678367b53381bff984c31Craig Mautner    Rect getStackBounds(int stackId) {
148967212cb542e6eeb308678367b53381bff984c31Craig Mautner        if (mStack != null) {
149967212cb542e6eeb308678367b53381bff984c31Craig Mautner            return mStack.mStackId == stackId ? new Rect(mBounds) : null;
150967212cb542e6eeb308678367b53381bff984c31Craig Mautner        }
151967212cb542e6eeb308678367b53381bff984c31Craig Mautner        Rect bounds = mFirst.getStackBounds(stackId);
152967212cb542e6eeb308678367b53381bff984c31Craig Mautner        if (bounds != null) {
153967212cb542e6eeb308678367b53381bff984c31Craig Mautner            return bounds;
154967212cb542e6eeb308678367b53381bff984c31Craig Mautner        }
155967212cb542e6eeb308678367b53381bff984c31Craig Mautner        return mSecond.getStackBounds(stackId);
156967212cb542e6eeb308678367b53381bff984c31Craig Mautner    }
157967212cb542e6eeb308678367b53381bff984c31Craig Mautner
15800af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /**
15900af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     * Create a new TaskStack relative to a specified one by splitting the StackBox containing
16000af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     * the specified TaskStack into two children. The size and position each of the new StackBoxes
16100af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     * is determined by the passed parameters.
16200af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     * @param stackId The id of the new TaskStack to create.
1635a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner     * @param relativeStackBoxId The id of the StackBox to place the new TaskStack next to.
16400af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     * @param position One of the static TASK_STACK_GOES_xxx positions defined in this class.
16500af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     * @param weight The percentage size of the parent StackBox to devote to the new TaskStack.
16600af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     * @return The new TaskStack.
16700af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     */
1685a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    TaskStack split(int stackId, int relativeStackBoxId, int position, float weight) {
1695a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner        if (mStackBoxId != relativeStackBoxId) {
1705a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            // This is not the targeted StackBox.
1715a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            if (mStack != null) {
1725a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner                return null;
1735a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            }
1745a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            // Propagate the split to see if the targeted StackBox is in either sub box.
1755a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            TaskStack stack = mFirst.split(stackId, relativeStackBoxId, position, weight);
176967212cb542e6eeb308678367b53381bff984c31Craig Mautner            if (stack != null) {
177c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner                return stack;
178c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner            }
1795a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            return mSecond.split(stackId, relativeStackBoxId, position, weight);
180c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        }
181c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
182967212cb542e6eeb308678367b53381bff984c31Craig Mautner        // Found it!
18305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        TaskStack stack = new TaskStack(mService, stackId, mDisplayContent);
184967212cb542e6eeb308678367b53381bff984c31Craig Mautner        TaskStack firstStack;
185967212cb542e6eeb308678367b53381bff984c31Craig Mautner        TaskStack secondStack;
1865a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner        if (position == TASK_STACK_GOES_BEFORE) {
1875a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            // TODO: Test Configuration here for LTR/RTL.
1885a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            position = TASK_STACK_TO_LEFT_OF;
1895a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner        } else if (position == TASK_STACK_GOES_AFTER) {
1905a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            // TODO: Test Configuration here for LTR/RTL.
1915a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            position = TASK_STACK_TO_RIGHT_OF;
1925a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner        }
193967212cb542e6eeb308678367b53381bff984c31Craig Mautner        switch (position) {
194967212cb542e6eeb308678367b53381bff984c31Craig Mautner            default:
1955a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            case TASK_STACK_TO_LEFT_OF:
1965a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            case TASK_STACK_TO_RIGHT_OF:
197967212cb542e6eeb308678367b53381bff984c31Craig Mautner                mVertical = false;
1985a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner                if (position == TASK_STACK_TO_LEFT_OF) {
199967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    mWeight = weight;
200967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    firstStack = stack;
201967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    secondStack = mStack;
202967212cb542e6eeb308678367b53381bff984c31Craig Mautner                } else {
203967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    mWeight = 1.0f - weight;
204967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    firstStack = mStack;
205967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    secondStack = stack;
206967212cb542e6eeb308678367b53381bff984c31Craig Mautner                }
207967212cb542e6eeb308678367b53381bff984c31Craig Mautner                break;
208967212cb542e6eeb308678367b53381bff984c31Craig Mautner            case TASK_STACK_GOES_ABOVE:
209967212cb542e6eeb308678367b53381bff984c31Craig Mautner            case TASK_STACK_GOES_BELOW:
210967212cb542e6eeb308678367b53381bff984c31Craig Mautner                mVertical = true;
211967212cb542e6eeb308678367b53381bff984c31Craig Mautner                if (position == TASK_STACK_GOES_ABOVE) {
212967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    mWeight = weight;
213967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    firstStack = stack;
214967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    secondStack = mStack;
215967212cb542e6eeb308678367b53381bff984c31Craig Mautner                } else {
216967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    mWeight = 1.0f - weight;
217967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    firstStack = mStack;
218967212cb542e6eeb308678367b53381bff984c31Craig Mautner                    secondStack = stack;
219967212cb542e6eeb308678367b53381bff984c31Craig Mautner                }
220967212cb542e6eeb308678367b53381bff984c31Craig Mautner                break;
221c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        }
222967212cb542e6eeb308678367b53381bff984c31Craig Mautner
22305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        mFirst = new StackBox(mService, mDisplayContent, this);
224967212cb542e6eeb308678367b53381bff984c31Craig Mautner        firstStack.mStackBox = mFirst;
225967212cb542e6eeb308678367b53381bff984c31Craig Mautner        mFirst.mStack = firstStack;
226967212cb542e6eeb308678367b53381bff984c31Craig Mautner
22705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        mSecond = new StackBox(mService, mDisplayContent, this);
228967212cb542e6eeb308678367b53381bff984c31Craig Mautner        secondStack.mStackBox = mSecond;
229967212cb542e6eeb308678367b53381bff984c31Craig Mautner        mSecond.mStack = secondStack;
230967212cb542e6eeb308678367b53381bff984c31Craig Mautner
231967212cb542e6eeb308678367b53381bff984c31Craig Mautner        mStack = null;
232967212cb542e6eeb308678367b53381bff984c31Craig Mautner        return stack;
233c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    }
234c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
23500af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** Return the stackId of the first mFirst StackBox with a non-null mStack */
23600af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    int getStackId() {
23700af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner        if (mStack != null) {
23800af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner            return mStack.mStackId;
239c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        }
24000af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner        return mFirst.getStackId();
241c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    }
242c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
24300af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    /** Remove this box and propagate its sibling's content up to their parent.
24400af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner     * @return The first stackId of the resulting StackBox. */
2454cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner    int remove() {
2464cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner        mDisplayContent.layoutNeeded = true;
2474cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner
2489e4f28cfa157fff89e42859edc9cce546508491fCraig Mautner        if (mParent == null) {
2494cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner            // This is the top-plane stack.
250a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: removing top plane.");
2519e4f28cfa157fff89e42859edc9cce546508491fCraig Mautner            mDisplayContent.removeStackBox(this);
2529e4f28cfa157fff89e42859edc9cce546508491fCraig Mautner            return HOME_STACK_ID;
2539e4f28cfa157fff89e42859edc9cce546508491fCraig Mautner        }
2544cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner
2554cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner        StackBox sibling = isFirstChild() ? mParent.mSecond : mParent.mFirst;
2564cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner        StackBox grandparent = mParent.mParent;
257a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner        sibling.mParent = grandparent;
2584cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner        if (grandparent == null) {
2594cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner            // mParent is a top-plane stack. Now sibling will be.
260a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent null");
2614cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner            mDisplayContent.removeStackBox(mParent);
2624cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner            mDisplayContent.addStackBox(sibling, true);
26300af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner        } else {
264a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72eCraig Mautner            if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent getting sibling");
2654cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner            if (mParent.isFirstChild()) {
2664cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner                grandparent.mFirst = sibling;
2674cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner            } else {
2684cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner                grandparent.mSecond = sibling;
2694cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner            }
270c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        }
2714cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner        return sibling.getStackId();
272c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    }
273c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
2745a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner    boolean resize(int stackBoxId, float weight) {
2755a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner        if (mStackBoxId != stackBoxId) {
2765a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner            return mStack == null &&
2775a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner                    (mFirst.resize(stackBoxId, weight) || mSecond.resize(stackBoxId, weight));
278967212cb542e6eeb308678367b53381bff984c31Craig Mautner        }
2795a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner        // Don't change weight on topmost stack.
2805a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner        if (mParent != null) {
2814cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner            mParent.mWeight = isFirstChild() ? weight : 1.0f - weight;
282967212cb542e6eeb308678367b53381bff984c31Craig Mautner        }
2835a449154d1795abe8e44b7bfe821d640b145e2c6Craig Mautner        return true;
284c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    }
28500af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner
286967212cb542e6eeb308678367b53381bff984c31Craig Mautner    /** If this is a terminal StackBox (contains a TaskStack) set the bounds.
287967212cb542e6eeb308678367b53381bff984c31Craig Mautner     * @param bounds The rectangle to set the bounds to.
288d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner     * @param underStatusBar True if the StackBox is directly below the Status Bar.
289967212cb542e6eeb308678367b53381bff984c31Craig Mautner     * @return True if the bounds changed, false otherwise. */
290d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner    boolean setStackBoxSizes(Rect bounds, boolean underStatusBar) {
291d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner        boolean change = false;
292d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner        if (mUnderStatusBar != underStatusBar) {
293d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner            change = true;
294d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner            mUnderStatusBar = underStatusBar;
295d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner        }
296967212cb542e6eeb308678367b53381bff984c31Craig Mautner        if (mStack != null) {
297d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner            change |= !mBounds.equals(bounds);
298b3b36ba13895d779159799341d432f6380a0ba8aCraig Mautner            if (change) {
299b3b36ba13895d779159799341d432f6380a0ba8aCraig Mautner                mBounds.set(bounds);
300d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner                mStack.setBounds(bounds, underStatusBar);
301b3b36ba13895d779159799341d432f6380a0ba8aCraig Mautner            }
302967212cb542e6eeb308678367b53381bff984c31Craig Mautner        } else {
303967212cb542e6eeb308678367b53381bff984c31Craig Mautner            mTmpRect.set(bounds);
304967212cb542e6eeb308678367b53381bff984c31Craig Mautner            if (mVertical) {
305967212cb542e6eeb308678367b53381bff984c31Craig Mautner                final int height = bounds.height();
306967212cb542e6eeb308678367b53381bff984c31Craig Mautner                int firstHeight = (int)(height * mWeight);
307967212cb542e6eeb308678367b53381bff984c31Craig Mautner                mTmpRect.bottom = bounds.top + firstHeight;
308d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner                change |= mFirst.setStackBoxSizes(mTmpRect, underStatusBar);
309967212cb542e6eeb308678367b53381bff984c31Craig Mautner                mTmpRect.top = mTmpRect.bottom;
310967212cb542e6eeb308678367b53381bff984c31Craig Mautner                mTmpRect.bottom = bounds.top + height;
311d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner                change |= mSecond.setStackBoxSizes(mTmpRect, false);
312967212cb542e6eeb308678367b53381bff984c31Craig Mautner            } else {
313967212cb542e6eeb308678367b53381bff984c31Craig Mautner                final int width = bounds.width();
314967212cb542e6eeb308678367b53381bff984c31Craig Mautner                int firstWidth = (int)(width * mWeight);
315967212cb542e6eeb308678367b53381bff984c31Craig Mautner                mTmpRect.right = bounds.left + firstWidth;
316d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner                change |= mFirst.setStackBoxSizes(mTmpRect, underStatusBar);
317967212cb542e6eeb308678367b53381bff984c31Craig Mautner                mTmpRect.left = mTmpRect.right;
318967212cb542e6eeb308678367b53381bff984c31Craig Mautner                mTmpRect.right = bounds.left + width;
319d76dcdcd98f1010b9439746314629cf7cba4df89Craig Mautner                change |= mSecond.setStackBoxSizes(mTmpRect, underStatusBar);
320967212cb542e6eeb308678367b53381bff984c31Craig Mautner            }
321967212cb542e6eeb308678367b53381bff984c31Craig Mautner        }
322967212cb542e6eeb308678367b53381bff984c31Craig Mautner        return change;
323967212cb542e6eeb308678367b53381bff984c31Craig Mautner    }
324967212cb542e6eeb308678367b53381bff984c31Craig Mautner
32505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    void resetAnimationBackgroundAnimator() {
32605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        if (mStack != null) {
32705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner            mStack.resetAnimationBackgroundAnimator();
32805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner            return;
32905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        }
33005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        mFirst.resetAnimationBackgroundAnimator();
33105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        mSecond.resetAnimationBackgroundAnimator();
33205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    }
33305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner
33405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    boolean animateDimLayers() {
33505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        if (mStack != null) {
33605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner            return mStack.animateDimLayers();
33705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        }
33805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        boolean result = mFirst.animateDimLayers();
33905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        result |= mSecond.animateDimLayers();
34005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        return result;
34105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    }
34205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner
34305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    void resetDimming() {
34405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        if (mStack != null) {
34505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner            mStack.resetDimmingTag();
34605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner            return;
34705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        }
34805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        mFirst.resetDimming();
34905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        mSecond.resetDimming();
35005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    }
35105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner
35205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    boolean isDimming() {
35305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        if (mStack != null) {
35405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner            return mStack.isDimming();
35505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        }
35605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        boolean result = mFirst.isDimming();
35705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        result |= mSecond.isDimming();
35805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        return result;
35905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    }
36005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner
36105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    void stopDimmingIfNeeded() {
36205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        if (mStack != null) {
36305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner            mStack.stopDimmingIfNeeded();
36405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner            return;
36505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        }
36605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        mFirst.stopDimmingIfNeeded();
36705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner        mSecond.stopDimmingIfNeeded();
36805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner    }
36905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner
370ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner    void switchUserStacks(int userId) {
371ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner        if (mStack != null) {
372ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner            mStack.switchUser(userId);
373ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner            return;
374ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner        }
375ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner        mFirst.switchUserStacks(userId);
376ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner        mSecond.switchUserStacks(userId);
377ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner    }
378ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner
3792eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner    void close() {
3802eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner        if (mStack != null) {
3812eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner            mStack.mDimLayer.mDimSurface.destroy();
3822eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner            mStack.mAnimationBackgroundSurface.mDimSurface.destroy();
3832eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner            return;
3842eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner        }
3852eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner        mFirst.close();
3862eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner        mSecond.close();
3872eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner    }
3882eb15342be5b075dda3df29b2b014a92ce13a5f8Craig Mautner
38900af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    public void dump(String prefix, PrintWriter pw) {
39000af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner        pw.print(prefix); pw.print("mParent="); pw.println(mParent);
39100af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner        pw.print(prefix); pw.print("mBounds="); pw.print(mBounds.toShortString());
3929e4f28cfa157fff89e42859edc9cce546508491fCraig Mautner            pw.print(" mVertical="); pw.print(mVertical);
3939e4f28cfa157fff89e42859edc9cce546508491fCraig Mautner            pw.print(" layoutNeeded="); pw.println(layoutNeeded);
394de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner        if (mFirst != null) {
395967212cb542e6eeb308678367b53381bff984c31Craig Mautner            pw.print(prefix); pw.print("mFirst="); pw.println(System.identityHashCode(mFirst));
39600af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner            mFirst.dump(prefix + "  ", pw);
397967212cb542e6eeb308678367b53381bff984c31Craig Mautner            pw.print(prefix); pw.print("mSecond="); pw.println(System.identityHashCode(mSecond));
39800af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner            mSecond.dump(prefix + "  ", pw);
399de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner        } else {
400de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner            pw.print(prefix); pw.print("mStack="); pw.println(mStack);
401de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner            mStack.dump(prefix + "  ", pw);
402de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner        }
403de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner    }
404de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner
405de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner    @Override
406de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner    public String toString() {
407de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner        if (mStack != null) {
408de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner            return "Box{" + hashCode() + " stack=" + mStack.mStackId + "}";
40900af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner        }
410967212cb542e6eeb308678367b53381bff984c31Craig Mautner        return "Box{" + hashCode() + " parent=" + System.identityHashCode(mParent)
411967212cb542e6eeb308678367b53381bff984c31Craig Mautner                + " first=" + System.identityHashCode(mFirst)
412967212cb542e6eeb308678367b53381bff984c31Craig Mautner                + " second=" + System.identityHashCode(mSecond) + "}";
41300af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner    }
414c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner}
415