1. 程式人生 > >【問題分析】Android 5.0版本SystemUI反覆發生ANR crash

【問題分析】Android 5.0版本SystemUI反覆發生ANR crash

問題描述

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