首页 > 代码库 > DisplayContent、StackBox、TaskStack笔记

DisplayContent、StackBox、TaskStack笔记

文章仅记录自己的一点理解,仅供自己参考。

每个显示设备,都有一个Display对象,DisplayManagerService专门管理这些Display。

1、DisplayContent()

<span style="font-size:18px;">    DisplayContent(Display display, WindowManagerService service) {
        mDisplay = display;
        mDisplayId = display.getDisplayId();
        display.getDisplayInfo(mDisplayInfo);
        isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
        mService = service;

        StackBox newBox = new StackBox(service, this, null);
        mStackBoxes.add(newBox);
        TaskStack newStack = new TaskStack(service, HOME_STACK_ID, this);
        newStack.mStackBox = newBox;
        newBox.mStack = newStack;
        mHomeStack = newStack;
    }</span>

对应在WMS中,每个Display对象都会给他new一个DisplayContent,保存跟这个Display相关的窗口等信息,这点从WMS的构造函数可以看出来。从DisplayContent()构造函数中还可以看出,每一个DisplayContent至少包含一个StackBox和TaskStack

createDisplayContentLocked()-->getDisplayContentLocked()-->WMS.newDisplayContentLocked()-->new DisplayContent();

<span style="font-size:18px;">WindowManagerService(){
         ............ 
        Display[] displays = mDisplayManager.getDisplays();
        for (Display display : displays) {
            createDisplayContentLocked(display);
        }
        ........
}</span>

2、mInitialDisplayWidth、mInitialDisplayHeight、mInitialDisplayDensity

保存的是初始屏幕宽度、高度、密度

3、mDisplayInfo

由第1条中的DisplayContent()构造函数中可以看出,mDisplayInfo就是从Display中获取的,保存着Display的相关信息。

4、layoutNeeded

当有窗口需要Layout时,layoutNeeded就会被设为true。

5、mStackBoxes

正常来说mStackBoxes中会保存两个StackBox,一个StackBox(0)里面只包含Launcher,另一个StackBox包含所有其他窗口。

①StackBox.mParent

<span style="font-size:18px;">    /** Non-null indicates this is mFirst or mSecond of a parent StackBox. Null indicates this
     * is this entire size of mDisplayContent. */</span>
mParent表示由哪个StackBox分裂而来,但是对于StackBox 0和StackBox 1的mParent都为null。

②StackBox.mBounds

WMS.performLayoutLockedInner()-->DisplayContent.setStackBoxSize()-->StackBox.setStackBoxSizes()-->mBounds.set(bounds);

bounds尺寸来源于mPolicy.getContentRectLw(bounds);

<span style="font-size:18px;">    public void getContentRectLw(Rect r) {
        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
    }</span>
对于720*1280尺寸的手机,(mContentLeft, mContentTop, mContentRight, mContentBottom)=(0,50,720,1280),踢出了状态栏高度,因此mBounds=(0,50,720,1280)
StackBox.mVertical

这个变量表示mFirst 和mSecond分裂方向是否是垂直分裂还是左右分裂,具体见split()函数。

/** Relative orientation of mFirst and mSecond. */

④StackBox.layoutNeeded

⑤StackBox.

⑥StackBox.mStack

/** Stack of Tasks, this is null exactly when mFirst and mSecond are non-null. */

6、StackBox.split()

StackBox分裂函数,分裂的两个StackBox分别保存在mFirst和mSecond中(二叉树方式分裂)。

<span style="font-size:18px;">    TaskStack split(int stackId, int relativeStackBoxId, int position, float weight) {
        if (mStackBoxId != relativeStackBoxId) {
            if (mStack != null) {
                return null;
            }
            TaskStack stack = mFirst.split(stackId, relativeStackBoxId, position, weight);
            if (stack != null) {
                return stack;
            }
            return mSecond.split(stackId, relativeStackBoxId, position, weight);
        }
        TaskStack stack = new TaskStack(mService, stackId, mDisplayContent);
        TaskStack firstStack;
        TaskStack secondStack;
        if (position == TASK_STACK_GOES_BEFORE) {
            position = TASK_STACK_TO_LEFT_OF;
        } else if (position == TASK_STACK_GOES_AFTER) {
            // TODO: Test Configuration here for LTR/RTL.
            position = TASK_STACK_TO_RIGHT_OF;
        }
        switch (position) {
            default:
            case TASK_STACK_TO_LEFT_OF:
            case TASK_STACK_TO_RIGHT_OF:
                mVertical = false;
                if (position == TASK_STACK_TO_LEFT_OF) {
                    mWeight = weight;
                    firstStack = stack;
                    secondStack = mStack;
                } else {
                    mWeight = 1.0f - weight;
                    firstStack = mStack;
                    secondStack = stack;
                }
                break;
            case TASK_STACK_GOES_ABOVE:
            case TASK_STACK_GOES_BELOW:
                mVertical = true;
                if (position == TASK_STACK_GOES_ABOVE) {
                    mWeight = weight;
                    firstStack = stack;
                    secondStack = mStack;
                } else {
                    mWeight = 1.0f - weight;
                    firstStack = mStack;
                    secondStack = stack;
                }
                break;
        }
        mFirst = new StackBox(mService, mDisplayContent, this);
        firstStack.mStackBox = mFirst;
        mFirst.mStack = firstStack;

        mSecond = new StackBox(mService, mDisplayContent, this);
        secondStack.mStackBox = mSecond;
        mSecond.mStack = secondStack;

        mStack = null;
        return stack;
    }
</span>
分裂的结果只有两种情况:

①分裂节点的StackBox.mStack转移到新的mFirst.mStack中,mSecond.mStack=new TaskStack(mService, stackId, mDisplayContent);

②分裂节点的StackBox.mStack转移到新的mSecond.mStack中,mFirst.mStack=new TaskStack(mService, stackId, mDisplayContent);

上面两种情况共同点是分裂节点StackBox.mStack会置null。

上述代码还可以归纳出,分裂节点就是二叉树的叶节点,只有叶节点才可以分裂,只有叶节点mStack变量才不为null。也可以说一个StackBox叶节点对应一个TaskStack。

从Android4.4源码来看,目前默认显示屏DEFAULT_DISPLAY的DisplayContent拥有两棵StackBox二叉树,这两个StackBox二叉树都还没有进行分裂过,只包含一个根节点。

8、TaskStack类

StackBox二叉树树的一个叶节点对应有一个TaskStack。

①TaskStack.mStackId,“stackId The id of the new TaskStack to create.”

②TaskStack.mTasks,保存着这个Task栈(TaskStack)中的所有Task。一个TaskStack中可以包含很多Task任务。

③TaskStack.mDimLayer

④TaskStack.mDimWinAnimator

⑤TaskStack.mAnimationBackgroundSurface

⑥TaskStack.mAnimationBackgroundAnimator