visible_windows生成逻辑和解析
visible_windows生成逻辑
在开发者选项中生成错误报告或命令行使用dumpstate,会生成一个bugreprot的压缩包,如
其中包含了一些dump信息,其中海有个压缩包
里面包含了一些可见窗口的控件信息,但用notepad打开却多是乱码
之前工作遇到过一个显示问题只有截图、简要log和上面bugreport,最后根据上面的控件信息结合截图然后排查代码找到疑点最后解决问题,这里介绍下上面窗口控件dump信息的生成和解析
首先找到其生成visible_windows.zip的代码:(frameworks/native/cmds/dumpstate/dumpstate.cpp)
可见这里主要是调用了cmd window dump-visible-window-views命令行,即使直接命令行调用也可以执行,其是调用的windowmanager的命令行即WindowManagerShellCommand.java中逻辑
查看其onCommand方法:
显然在调用dump-visible-window-views命令时,其会执行runDumpVisibleWindowViews方法
runDumpVisibleWindowViews主要逻辑时遍历窗口,如果窗口可见则调用窗口(WindowState)的mClient.executeCommand方法,这里mClient对端是ViewRootImpl的一个内部类W,所以,这里最后会遍历可见窗口执行其ViewRootImpl中的executeCommand方法
executeCommand方法这里显然根本逻辑只有一行,即调用ViewDebug的dispatchCommand方法,其参数view是对应窗口的控件树的根节点,其参数command是ViewDebug.REMOTE_COMMAND_DUMP_ENCODED即DUMP_ENCODED,其参数parameters是null,其参数clientStream是之前创建的输出流
继续查看下ViewDebug的dispatchCommand方法
在该场景下其调用的是dumpEncoded方法
这里主要创建了一个ViewHierarchyEncoder,后面控件也主要是通过这里写入的
encoder.addProperty
先看下这里最开始写如的widnow:left和window:top数据,其都是调用ViewHierarchyEncoder的addProperty方法
这里createPropertyIndex方法如下,其维护了一个属性名的map,其key是属性名,value是记录的该属性名出现的index,如果已经添加过对应属性名,这里则返回其对应index,如果没有添加过,则将心出现的属性名添加到map中(mPropertyNames),并将其新的index(根据属性名出现顺序从1开始递增)添加到map中
再查看下writeShort和writeInt方法,其逻辑相似,都是先写入一个标记字母表示数据类型,然后写入对应数据
view.encode
然后看下view.encode方法
beginObject和endObject(ViewHierarchyEncoder)
其中addProperty之前介绍过了,这里不重复,这里beginObject看着主要是对对应控件的信息两边加个标记,类似于加个括号以区分
encodeProperties(View和ViewGroup)
这里只分析下View和ViewGroup的方法,其他可能也有实现encodeProperties方法,但其基本逻辑作用都是相似的
先看下ViewGroup的encodeProperties方法:
这里首先调用了super方法,也即会先调用View. encodeProperties方法
addProperty方法之前分析过,添加写入的属性和其值
然后是对控件的子控件进行遍历,这里会先调用encoder的addPropertyKey方法,其与addProperty相似,只是不写入具体的数据值而已,这里也只是起到一个隔离的作用,然后即是最关键的调用子控件的encode方法,这样就可以将控件树和其各控件的属性打印出来
然后再看下View的encodeProperties,这里打印了很多控件的属性,包括对应LayoutParams、Theme等各种信息
encoder.endStream
在前面的addProperty方法分析中有介绍其添加属性名和属性值时,属性名并不是直接写入的,而是先生成一个属性名的map,然后写入的是map中属性名对应的value,也相当于其index,而这里就是将map的信息写入(mPropertyNames),相当于一个索引
总结
根据前面的分析,总结下其写入数据的逻辑,这里一般有两种数据,一种是作为类似括号功能的标记用以区分不同控件/不同作用的数据,一种是具体的控件的属性等,其添加数据写入,会生成一个类似索引表的map,将属性名都放到索引表中,写入数据时不直接写属性名,而是写入其对应索引,然后写入其值,在最后,则写入索引表信息
visible_windows解析
弄明白了生成的过程,其实解析也就不难了
而在Android源码中其实也有个简易的例子:
frameworks/base/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/
这里参考源码中的代码结合上面分析写个完整的解析的代码(源码中Decoder.java可直接使用,这个也是包含最基本的解析数据的逻辑)
先第一步使用Decoder将数据进行解析打印出来(以NavigationBar的为例,这里只是当作例子实现下功能,代码上可能有些地方并不算完善)
如上即是解析打印出来的文件,虽然并不完善,但可以看到已经没有乱码了,而结合之前的生成逻辑,根据这里的打印也可以识别出信息内容了
第一行是1,查找打印出来的索引表,其代表window:left,第二行是0,表示window:left是0
第三行是2,查找打印出来的索引表,其代表window:top,第四行是2792,表示window:top是2792
这几行也符合前面生成逻辑里的最开始的打印信息
要将解析更完善一步的话也很简单,最后面的map是索引表,可将索引表的具体信息直接替换成前面的索引index,这样看着更方便,这里不进一步举例
标签:控件,调用,这里,windows,写入,visible,解析,方法,属性 From: https://www.cnblogs.com/luoliang13/p/18250713