WMS窗口层级结构

193 阅读3分钟

窗口容器层级结构

// 最末端的节点是 WindowState
class WindowState extends WindowContainer<WindowState>

// 其次是 WindowToken 和其子类
class WindowToken extends WindowContainer<WindowState>
class ActivityRecord extends WindowToken
class WallpaperWindowToken extends WindowToken

// 中间是 Task, Activity堆栈
class Task extends TaskFragment(class TaskFragment extends WindowContainer<WindowContainer>)

// 再次是 DisplayArea
class TaskDisplayArea extends DisplayArea<WindowContainer>
class DisplayArea.Tokens extends DisplayArea<WindowToken>
class DisplayContent.ImeContainer extends DisplayArea.Tokens

// 再次是 DisplayContent, 表示一个屏幕
class DisplayContent extends RootDisplayArea(extends DisplayArea(<T extends WindowContainer> extends WindowContainer))

// 最后是 RootWindowContainer
class RootWindowContainer extends WindowContainer<DisplayContent>

窗口基类 WindowContainer

所有容器都继承自 WindowContainer。下面介绍 WIndowContainer 的重要成员和方法:

层级关系:

  • mParent 表示父级窗口;
  • mChildren 表示子窗口列表;列表按子节点在屏幕显示的z轴顺序排列, 最上面的窗口容器在列表尾部
  • addChild(), setParent(), 增加子窗口、设置父窗口;
  • positionChildAt(), reparent(),改变子窗口的位置,重新设置父窗口;
  • mTreeWeight 在树状结构中的权重,包括所有子窗口和当前窗口;

Surface 和动画:

  • mSurfaceControl 每个窗口的 Surface
  • mSurfaceAnimator 执行动画

Z轴:

  • setLayer(), assignLayer() 设置当前窗口的 layer
  • assignChildLayer() 设置子窗口的 layer

// 1 组织, 层级结构
// 2 Surface 和 动画
// 3
class WindowContainer<E extends WindowContainer> {
    // 组织
    private WindowContainer<WindowContainer> mParent = null;

    // 该窗口容器的子节点列表。列表按子节点在屏幕显示的z轴顺序排列, 最上面的窗口容器在列表尾部.
    protected final WindowList<E> mChildren = new WindowList<E>();

    // 每个WC有一个 Surface
    protected SurfaceControl mSurfaceControl;

    // 动画
    protected final SurfaceAnimator mSurfaceAnimator;

    /** The parent leash added for animation. */
    private SurfaceControl mAnimationLeash;

    final TransitionController mTransitionController;

    // Leash 作用
    onAnimationLeashCreated();

    // 按照index 添加入 mChildren, 同时为 child.setParent(this);
    void addChild(E child, int index)

    // 按照比较器加入 mChildren
    protected void addChild(E child, Comparator<E> comparator)

    // 移动一个 child, includingParents递归移动parent
    void positionChildAt(int position, E child, boolean includingParents)
}

根容器 RootWindowContainer

RootWindowContainer 是窗口层级的根容器。大遍历从 RootWindowContainer 开始,遍历所有屏幕。

在 WindowManagerService 构造方法中对 RootWindowContainer 进行初始化。

屏幕 DisplayContent

DisplayContent 表示一个屏幕。

SystemServer 创建 AMS 和 WMS,调用 mActivityManagerService.setWindowManager(wm) 开始初始化所有屏幕,并添加为根容器的子窗口,并且同时初始化默认屏幕的 TaskDisplayArea 和 root home task,并添加到其父窗口中。

DisplayContent 类中还管理 应用过渡动画、屏幕配置、屏幕方向、输入法键盘等,以及执行布局。

void setWindowManager(WindowManagerService wm) {
    ...
    // 初始化所有屏幕
    final Display[] displays = mDisplayManager.getDisplays();
    for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
        final Display display = displays[displayNdx];
        final DisplayContent displayContent =
                new DisplayContent(display, this, mDeviceStateController);
        addChild(displayContent, POSITION_BOTTOM);
        if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
            mDefaultDisplay = displayContent;
        }
    }
    // 同时初始化默认屏幕的 TaskDisplayArea 和 root home task,并添加到父窗口中
    final TaskDisplayArea defaultTaskDisplayArea = getDefaultTaskDisplayArea();
    defaultTaskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
    positionChildAt(POSITION_TOP, defaultTaskDisplayArea.mDisplayContent,
            false /* includingParents */);
}

// 应用过渡动画相关
final AppTransition mAppTransition;
final AppTransitionController mAppTransitionController;
boolean mSkipAppTransitionAnimation = false;

final ArraySet<ActivityRecord> mOpeningApps = new ArraySet<>();
final ArraySet<ActivityRecord> mClosingApps = new ArraySet<>();
final ArraySet<WindowContainer> mChangingContainers = new ArraySet<>();

// 输入法键盘相关
WindowState mInputMethodWindow;
private WindowState mImeLayeringTarget;
private InputTarget mImeInputTarget;

屏幕显示区域 DisplayAreas

DisplayAreas 表示一块屏幕显示区域,可以用于分屏。DisplayAreas 可以嵌套。TaskDisplayArea 表示可以包含应用窗口的屏幕显示区域,ImeContainer 表示输入法键盘的显示区域。

DisplayArea 有3种类别,用于确保所包含的窗口有正确的Z轴顺序。其中,ImeContainer 是 ABOVE_TASKS,包含壁纸的 Display 是 BELOW_TASKS。

enum Type {
    // 只能包含在应用窗口层级/TASK之上的WindowToken/DisplayArea
    ABOVE_TASKS,
    // 只能包含在应用窗口层级/TASK之下的WindowToken/DisplayArea
    BELOW_TASKS,
    // 可以包含任何WindowToken/DisplayArea
    ANY;
}

Activity堆栈 Task 和 TaskFragment

TaskFragment 可以包含 ActivityRecord,也可以嵌套。用于管理 Activity 生命周期和可见性。

Task 维护一组相同亲和度的 Activity,可以用于显示最近任务,也可以嵌套。

Root Task 指父窗口不是其它 Task;Leaf Task 指子窗口不是其它 Task。

WindowToken, ActivityRecord, WallpaperWindowToken

ActivityRecord, 应用窗口的令牌; WallpaperWindowToken,壁纸窗口的令牌; WindowToken,其它窗口的令牌;

其成员 windowType 是其子容器窗口的 windowType;

WindowState

表示一个窗口, mBaseLayer,代表窗口Z轴,如果是子窗口类型,这个值是其父窗口的layer mSubLayer,子窗口类型的Z轴