文章目录
- 背景
- Not have a Focused Window介绍
- 分析这类no Foucsed ANR技巧分享
- **1、区分FocusedApplication和FocusedWindow**
- FocusedApplication
- FocusedWindow
- 2 分析日志和dumpsys部分
- events日志分析部分
- dumpsys SF中焦点窗口显示情况
- dumpsys window中焦点窗口是否计算正常
- 检查应用生命周期,看是窗口否显示
- 检查其他性能卡顿相关日志
背景
在马哥的wms实战课程中已经详细给大家讲解过Focused Window相关的知识,同时教大家详细分析了Not have a Focused Window这个类型的ANR相关案例。
但是在实际系统fw开发工作中,app层面报出的No Focused Window类型的ANR其实非常非常多,而且每一个ANR都可能情况不一样,所以针对这类 no Focused Window类型的ANR问题,用本文我们进行相关的一些相关于分析技巧总结归纳,大家以后分析都按照这个固定套路去分析哈。
Not have a Focused Window介绍
ANR是Android稳定性问题分析的一个难点,其中比较常见的一种是窗口无焦点Not have a Focused Window,这类无焦点窗口ANR相比其他Application not response无响应更难分析。
focused ANR一定是wms问题?
如果对该ANR的原理不了解,会直接认为窗口焦点是WMS控制,出现无焦点就一定是WMS导致。
其实不是这样哈,这种无焦点窗口ANR还是需要从ANR产生原理触发,结合系统相关日志,dumpsys等综合分析,才可以得出初步结论原因,也就是并不是这种no focused anr就是wms逻辑错误导致无焦点的,大部分情况下其实是属于系统某些卡顿,性能,或者app不正确操作设置等导致的,真正说wms自身逻辑错误导致no focused window其实还是很少哈。
所以当app产生这类no focused window的anr大家不要着急甩锅给系统wms负责的哈,应该自己学会来综合分析,不然很有可能很快甩锅回来。
无焦点ANR产生条件
无焦点类型的ANR不是所有输入事件都会触发。
在需要焦点窗口的input事件派发时,会去寻找焦点窗口,找不到的时候,会超时计时,过了超时时间,触发ANR
因此只有Key事件,和非触摸的Motion事件(比如滚轮),这种需要焦点窗口的,才会导致该类ANR。
所以大家在分析日志时候就会发现,一般只有key事件(包括实体按键和导航栏那种按钮模拟key事件)要派发才会有这类anr,只是手指触摸一般没有这类anr问题。
分析这类no Foucsed ANR技巧分享
其实针对这类anr问题,已经在wms实战课程中有给大家讲解过相关的案例分析,这里再进行总结归纳一下,方便大家记忆回顾课程。
1、区分FocusedApplication和FocusedWindow
FocusedApplication
FocusedApplication——对应Activity
FocusedWindow——对应窗口,但不一定是上述Activity的窗口。比如,在launcher上下拉状态栏,两者并不一致
FocusedApplications:displayId=0,name='ActivityRecord{173024276 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t20}',dispatchingTimeout=5000ms FocusedWindows:displayId=0,name='7556327 NotificationShade'FocusedApp是WMS通过JNI向InputDispatcher设置的,需要改变FocusedApp的地方不少,特殊场景是Activity在Display/Task间切换,比如:
resumeTopActivity,moveTaskToFront等方法。
frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
*/booleansetFocusedApp(ActivityRecord newFocus){if(newFocus!=null){finalDisplayContent appDisplay=newFocus.getDisplayContent();// Called even if the focused app is not changed in case the app is moved to a different// TaskDisplayArea.onLastFocusedTaskDisplayAreaChanged(newFocus.getDisplayArea());}if(mFocusedApp==newFocus){returnfalse;}ProtoLog.i(WM_DEBUG_FOCUS_LIGHT,"setFocusedApp %s displayId=%d Callers=%s",newFocus,getDisplayId(),Debug.getCallers(4));finalTask oldTask=mFocusedApp!=null?mFocusedApp.getTask():null;finalTask newTask=newFocus!=null?newFocus.getTask():null;mFocusedApp=newFocus;if(oldTask!=newTask){if(oldTask!=null)oldTask.onAppFocusChanged(false);if(newTask!=null)newTask.onAppFocusChanged(true);}getInputMonitor().setFocusedAppLw(newFocus);returntrue;}这里也有对应的proto日志,大家可以考虑开放WM_DEBUG_FOCUS_LIGHT这个Proto的TAG。
当然也可以通过dumpsys window ,或者dumpsys input查看当前的FocusApp。
FocusedWindow
FocusedWindow是由WMS计算出一个焦点窗口(每个Display有自己的),将它传给SurfaceFlinger处理之后,再向InputDispatcher设置的。
早期的Android版本,WMS是直接向InputDispatcher设置的,现在传给SF处理,可能是考虑到窗口最终是否显示,是由SF决定的,这样更准确。
因此,WMS中计算出的焦点窗口,如果在SurfaceFlinger处理后处于非显示状态(被遮挡?),那么在InputDispatcher中,它是不能成为焦点窗口的。
因为在SF和Input需要进一步处理,所以WMS进行数据传递时,传递两种数据:
1、焦点窗口
2、各个窗口的信息
2 分析日志和dumpsys部分
events日志分析部分
定位anr问时间点:
adb logcat -b events|grepanr一般会有am_anr打印,在这个日志的时间点前面开始找对应的input_focus相关日志。
focus相关日志
使用如下命令对focus相关切换进行跟踪
adb logcat -b events|grepinput得到如下结果
01-2711:43:42.634718743I input_focus:[Focus request 20c1a6e com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher,reason=UpdateInputWindows]01-2711:43:42.654718828I input_focus:[Focus leaving7556327NotificationShade,reason=setFocusedWindow]01-2711:43:42.654718828I input_focus:[Focus entering 20c1a6e com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher,reason=setFocusedWindow]request只是代表了请求焦点,entering才是代表真正在inputdispatcher层面获取焦点,所以很多anr情况都是有request请求焦点打印,但是没有对应的entering打印,这时候就可以确定大概anr的时间范围,然后在这个时间范围内进行dumpsys SF等窗口。
dumpsys SF中焦点窗口显示情况
在第二步确定大概anr的时间区间后进行dumpsys SurfaceFlinger看看对应的Layer信息上面这种是正常情况下有焦点的,可以看到右边Focused Window有打上 * ,如果都没有一个 * 那就需要查看对应的Layer情况。
这种一般排查方向就是看看这个window是否真的在sf中显示正常,大小,遮盖,或者直接layer没有显示等情况,一般都是sf可以得出layer情况,从而anr得出直接原因,但是根本原因的话就需要根据具体layer情况进一步分析。
dumpsys window中焦点窗口是否计算正常
具体命令
adb shell dumpsys window|grep Focus-C5正常可以看到如下结果
如果这里都不正常那么就需要查看wms部分的焦点窗口FocusedWindow的计算逻辑,放开对应的日志排查,排除方向在WMS。
检查应用生命周期,看是窗口否显示
adb logcat -b events | grep wm_on主要看看对应的app的生命周期是否正常等,最重要还得看看wm_on_resume时间是不是延迟了,因为app自身一直没有执行导致的窗口没有显示等。
检查其他性能卡顿相关日志
adb logcat -b all | grep Slow
看看是否有自身进程相关慢处理日志,主要是定位窗口显示慢原因原文地址
https://mp.weixin.qq.com/s/oYWumjZg8gEV_zybsAEwGA
更多framework实战开发干货资料,请关注下面“千里马学框架”