android的anr
『壹』 Android ANR 機制
廣播的 ANR 處理相對簡單,主要是再次判斷是否超時、記錄日誌,記錄 ANR 次數等。然後就繼續調用 processNextBroadcast 函數,處理下一條廣播了。
ContentProvider 超時為 CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s
Activity 的 ANR 是相對最復雜的,也只有 Activity 中出現的 ANR 會彈出 ANR 提示框。
最終的表現形式是:彈出一個對話框,告訴用戶當前某個程序無響應,輸入一大堆與 ANR 相關的日誌,便於開發者解決問題。
InputDispatching:
Activity 最主要的功能之一是交互,為了方便交互,Android 中的 InputDispatcher 會發出操作事件,最終在 InputManagerService 中發出事件,通過 InputChannel,向 Activity 分發事件。交互事件必須得到響應,如果不能及時處理,IMS 就會報出 ANR,交給 AMS 去彈出 ANR 提示框。
KeyDispatching:
如果輸入是個 Key 事件,會從 IMS 進入 ActivityRecord.Token.keyDispatchingTimeOut,然後進入 AMS 處理,不同的是,在 ActivityRecord 中,會先截留一次 Key 的不響應,只有當 Key 連續第二次處理超時,才會彈出 ANR 提示框。
窗口焦點:
Activity 總是需要有一個當前窗口來響應事件的,但如果遲遲沒有當前窗口(獲得焦點),比如在 Activity 切換時,舊 Activity 已經 onPause,新的 Activity 一直沒有 onResume,持續超過 5 秒,就會 ANR。
App 的生命周期太慢,或 CPU 資源不足,或 WMS 異常,都可能導致窗口焦點。
1. 判斷是否有 focused 組件以及 focused Application:
這種一般是在應用啟動時觸發,比如啟動時間過長在這過程中觸發了 keyevent 或者 trackball moteionevent 就會出現。
對應於
2. 判斷前面的事件是否及時完成:
對應於
出現這種問題意味著主線程正在執行其他的事件但是比較耗時導致輸入事件無法及時處理。
InputDispatcher 超時是最常見的 ANR 類型,而且其類型也比較多。
當用戶觸摸屏幕或者按鍵操作,首次觸發的是硬體驅動,驅動收到事件後,將該相應事件寫入到輸入設備節點, 這便產生了最原生態的內核事件。接著,輸入系統取出原生態的事件,經過層層封裝後成為 KeyEvent 或者 MotionEvent ;最後,交付給相應的目標窗口(Window)來消費該輸入事件。可見,輸入系統在整個過程起到承上啟下的銜接作用。
Input 模塊的主要組成:
每一個應用進程都會有一個 SignalCatcher 線程,專門處理 SIGQUIT,來到 art/runtime/signal_catcher.cc :
當應用發生 ANR 之後,系統會收集許多進程,來 mp 堆棧,從而生成 ANR Trace 文件。收集的第一個,也是一定會被收集到的進程,就是發生 ANR 的進程。接著系統開始向這些應用進程發送 SIGQUIT 信號,應用進程收到 SIGQUIT 後開始 mp 堆棧。
[1] developer ANRs
[2] Android ANR 分析詳解
[3] 看完這篇 Android ANR 分析,就可以和面試官裝逼了!
[4] 微信 Android 團隊手把手教你高效監控 ANR
[5] Input 系統—ANR 原理分析 - Gityuan
[6] 徹底理解安卓應用無響應機制 - Gityuan
[7] 理解 Android ANR 的觸發原理 - Gityuan
『貳』 【Android】ANR是如何產生的
眾所周知,Android的輸入事件是通過 InputReader 監聽系統 dev/input 下的文件來獲取輸入事件,並由 InputDispatcher 來進行分發的。
而ANR事件就是在 InputDispatcher 中產生的。
InputDispatcher 內部維護了一個線程 InputDispatcherThread ,輸入事件在這個線程中進行處理。這個線程在 InputManager 中進行創建和啟動。
它只做了一件事,就是無限調用 dispatchOnce() 進行事件分發。
dispatchOnce() 會調用 dispatchOnceInnerLocked() 進行事件分發,而如果判斷出當前事件是觸摸事件,則會又調用 dispatchMotionLocked() 來分發觸摸事件。在處理結束之後,會阻塞直到下一次事件的到來。
dispatchMotionLocked() 會調用 () 查找觸摸事件對應窗口目標並進行分發。如果當前窗口尚有未處理完的事件,則會調用 handleTargetsNotReadyLocked 處理。
handleTargetsNotReadyLocked 會判斷目標事件等待時間,如果其大於5秒,則會調用 onANRLocked 進入ANR流程。
以上便是ANR的產生過程。
ANR的產生有兩個必要條件:
/frameworks/native/services/inputflinger/InputDispatcher.cpp
Android輸入事件分發與攔截