核心内容摘要
告别无效社交,遇见“操人软件”——重塑人际关系的秘密武器
文章目录背景Not have a Focused Window介绍分析这类no Foucsed ANR技巧分享**
区分FocusedApplication和FocusedWindow**FocusedApplicationFocusedWindow2 分析日志和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实战课程中有给大家讲解过相关的
案例分析这里再进行
总结归纳一下方便大家记忆回顾课程。
区分FocusedApplication和FocusedWindowFocusedApplicationFocusedApplication——对应ActivityFocusedWindow——对应窗口但不一定是上述Activity的窗口。
比如在launcher上下拉状态栏两者并不一致FocusedApplications:displayId0,nameActivityRecord{173024276 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t20},dispatchingTimeout5000ms FocusedWindows:displayId0,name7556327 NotificationShadeFocusedApp是WMS通过JNI向InputDispatcher设置的需要改变FocusedApp的地方不少特殊场景是Activity在Display/Task间切换比如resumeTopActivitymoveTaskToFront等方法。
frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java*/booleansetFocusedApp(ActivityRecord newFocus){if(newFocus!null){finalDisplayContent appDisplaynewFocus.getDisplayContent();// Called even if the focused app is not changed in case the app is moved to a different// TaskDisplayArea.onLastFocusedTaskDisplayAreaChanged(newFocus.getDisplayArea());}if(mFocusedAppnewFocus){returnfalse;}ProtoLog.i(WM_DEBUG_FOCUS_LIGHT,setFocusedApp %s displayId%d Callers%s,newFocus,getDisplayId(),Debug.getCallers(
);finalTask oldTaskmFocusedApp!null?mFocusedApp.getTask():null;finalTask newTasknewFocus!null?newFocus.getTask():null;mFocusedAppnewFocus;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。
FocusedWindowFocusedWindow是由WMS计算出一个焦点窗口每个Display有自己的将它传给SurfaceFlinger处理之后再向InputDispatcher设置的。
早期的Android版本WMS是直接向InputDispatcher设置的现在传给SF处理可能是考虑到窗口最终是否显示是由SF决定的这样更准确。
因此WMS中计算出的焦点窗口如果在SurfaceFlinger处理后处于非显示状态被遮挡那么在InputDispatcher中它是不能成为焦点窗口的。
因为在SF和Input需要进一步处理所以WMS进行数据传递时传递两种数据
焦点窗口
各个窗口的信息2 分析日志和dumpsys部分events日志分析部分定位anr问时间点adb logcat -b events|grepanr一般会有am_anr打印在这个日志的时间点前面开始找对应的input_focus相关日志。
focus相关日志使用如下命令对focus相关切换进行跟踪adb logcat -b events|grepinput得到如下结果
:43:
4
634718743I input_focus:[Focus request 20c1a6e com.android.launcher3/com.android.launcher
uioverrides.QuickstepLauncher,reasonUpdateInputWindows]
:43:
4
654718828I input_focus:[Focus leaving7556327NotificationShade,reasonsetFocusedWindow]
:43:
4
654718828I input_focus:[Focus entering 20c1a6e com.android.launcher3/com.android.launcher
uioverrides.QuickstepLauncher,reasonsetFocusedWindow]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实战开发干货资料请关注下面“千里马学框架”