【问题分析】Android 5.0版本SystemUI反复发生ANR crash

版权声明:本文为博主原创文章, 只要标明出处即可转载. https://blog.csdn.net/HaoBBNuanMM/article/details/60468122

问题描述

Android 5.0版本上按照下述的步骤, 会触发SystemUI进程反复ANR然后crash的问题

1.       下拉systemui面板

2.       adb –host shell

3.       ps –ax systemui

4.       kill -SIGSTOP <systemui pid>

5.       然后在systemui面板中不停触摸,由于systemui 已经stop 所以会触发一次ANR,紧接着就进一步触发本问题中提到的systemui 反复ANR,AMS 反复restart system

Root Cause分析:

如上面的ANR 时序分析图所示,  导致问题的关键步骤是InputMonitor模块处理notifyANR过程中

longtimeout = ActivityManagerNative.getDefault().inputDispatchingTimedOut(...

这里timeout的返回值会被InputDispacther模块作为下一次超时判断的计算变量,AMS 返回的timeout 单位是ms,而InputDispatcher模块中使用的单位是nanos,差别为10^6级别.  InputMonitor模块没有及时将ms级别的timeout转换成nanos,就直接将timeout值送回InputDispacther了(实际上这里的timeout要求下次检查时间超时等待为8秒钟)

最终导致InputDispatcher模块错误的将一个ms级别的timout(没有在换算成为nano second,差了10^6级别)值去计算下一次事件超时等待时间

mInputTargetWaitTimeoutTime= now() + newTimeout;

从而导致systemui 还没有足够的时间去重新启动(本来应用有8秒超时等待时间),而下一次InputDispatcher dispatchOnce调用马上发生事件派发超时,进而导致重复发生了 ANR kill systemui 的时序过程

解决方案

try {
    // Notify the activity manager about the timeout and let it decide whether
    // to abort dispatching or keep waiting.
    long timeout = ActivityManagerNative.getDefault().inputDispatchingTimedOut(
               windowState.mSession.mPid, aboveSystem, reason);
    if (timeout >= 0) {
        // The activity manager declined to abort dispatching.
        // Wait a bit longer and timeout again later.
        return timeout * 1000000L; // nanoseconds
    }
 } catch (RemoteException ex) {
 }


如上图所示, 在<AOSP>/framework/base/services/core/java/com/android/server/wm/InputMonitor.java 的notifyANR 函数中将return 的timeout  (ms) 乘以 1000000换算为nanosecond再进行返回. Google 在后续的Android 版本中已经按照这个方式做了fix

猜你喜欢

转载自blog.csdn.net/HaoBBNuanMM/article/details/60468122