背景:
针对wms课程中经常讲解的窗口层级结构树部分,有学员反应有的看不出窗口具体位于0-36层的具体哪一层的问题。

比如想看Leaf:3:12中的下面Shell窗口的层级是啥,这个同学就不太好理解了,到底是位于第3层还是第12层呢?
其实这个问题层级位于哪里,宏观上理解也容易,大家可以如下方式理解:
因为这里的Leaf:3:12本身属于一个范围节点,而且本身这个节点下面就一个子节点,也就是说3-12层都是最后都是只装了一个窗口,没有再细分其他层级窗口节点,所以你可以认为这个3-12是一个整体上的一层既可以。无论ShellDropTarget窗口位于3-12哪一层都不会运行这个窗口的显示顺序。
总结就是把3-12层看成一个整体层级一个大层既可以,反正3-12只有一个ShellDropTarget窗口,无论他是在3层,5层,12层都是不会影响他的在系统整体显示z轴顺序。
但是有学员提出,我就想要知道这个窗口具体的是位于哪一层,可否有办法呢?

这个问题我们的优秀学员“汽车人”在vip群就有进行详细回答,“汽车人”兄弟也算大家的师兄,给大家也分享过很多干货哈,最后感谢“汽车人”兄弟干货投稿,给大家分享了一个dumpsys 层级结构树的改进方案,带上window的具体0-36层级数字。
优秀学员汽车人投稿:
dumpsys activity containers命令查看层级结构时,发现有些WindowToken我们不知道它具体在0-36的哪一层,比如ShellDropTarget所属的windowToken,我们只知道它在3:12层这个区间,不知道具体哪一层。

在学习层级结构树时,我们知道windowToken其实是在WindowManagerPolicy的getWindowLayerFromTypeLw()方法中去看对应的层级,这里的关键就是知道type这个属性。

这个type其实是WindowToken的windowType属性,在WindowToken构造时被赋值,对应应用端添加窗口时传递的参数,比如:
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;`
如果想要dumpsys activity containers命令也能查看到windowToken的具体层级很简单。
void dumpActivityContainersLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER CONTAINERS (dumpsys activity containers)");
mRootWindowContainer.dumpChildrenNames(pw, "");
pw.println(" ");
}
顺着这个命令找对应代码,很快找到对每个层级信息的打印是在这个方法里:
public void dumpChildrenNames(PrintWriter pw, String prefix, boolean isLastChild) {
//省略
pw.print(prefix + (isLastChild ? "└─ " : "├─ "));
pw.println(getName()//这里会调用toString()
+ " type=" + actType
+ " mode=" + winMode
+ " override-mode=" + overrideWinMode
+ " requested-bounds=" + getRequestedOverrideBounds().toShortString()
+ " bounds=" + getBounds().toShortString());
String childPrefix = prefix + (isLastChild ? " " : "│ ");
for (int i = getChildCount() - 1; i >= 0; --i) {
final E cc = getChildAt(i);
cc.dumpChildrenNames(pw, childPrefix, i == 0 /* isLastChild */);
}
}
注意此处的getName()其实是调用toString()方法,而WindowToken的toString()如下:

其实是打印了windowType的,而WindowToken本身就有方法获取对应层级:
int getWindowLayerFromType() {
return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens,
mRoundedCornerOverlay);
}
所以,只需要对toString()方法改成如下即可:
@Override
public String toString() {
if (stringName == null) {
stringName = "WindowToken{" + Integer.toHexString(System.identityHashCode(this))
+ " type=" + windowType + " " + token + ",layer:"+getWindowLayerFromType()+"}";
}
return stringName;
}
最终dumpsys activity containers命令效果:
可以看到,WindowToken都能显示具体层级了,壁纸的专用WallpaperWindowToken我没修改,所以它没显示,不过也不需要。
再次感谢“汽车人”兄弟投稿,大家记得积极转发点赞哈。
6563

被折叠的 条评论
为什么被折叠?



