Input ANR的觸發流程

以MTK平臺爲例

1.CPU信息查看

當ANR發生時,會生成db文件;其中SYS_CPU_INFO會包含cpu的信息。

Tasks: 1976 total, 31 running,1928 sleeping, 0 stopped, 0 zombie
Mem: 2866928k total, 2826828k used, 40100k free, 6852k buffers
Swap: 1048572k total, 353344k used, 695228k free, 520232k cached
400%cpu 283%user 168%nice 102%sys 154%idle 2%iow 0%irq 0%sirq 0%host

參數說明:

user:CPU在用戶態的運行時間,不包括nice值爲負數的進程運行的時間
nice: CPU在用戶態並且nice值爲負數的進程運行的時間
sys:CPU在內核態運行的時間
idle:CPU空閒時間,不包括iowait時間
iow:CPU等待I/O操作的時間
irq:CPU硬中斷的時間
sirq:CPU軟中斷的時間

相應的cpu的使用率,也可以通過如下命令實時抓取:# cat /proc/stat。

此外,在dump_cpuinfo文件中也可以看到某一時段內的cpu 平均負載信息。以下爲某臺XXXX上抓取的信息。

Load: 19.89 / 21.61 / 22.07
CPU usage from 67280ms to 14941ms ago (2018-09-01 14:49:32.291 to 2018-09-01 14:50:24.630):
  85% 1161/com.android.systemui: 82% user + 3.2% kernel / faults: 29917 minor 22 major
  31% 957/system_server: 27% user + 4.2% kernel / faults: 4969 minor 6 major

  20% 25137/com.android.vending: 14% user + 6.4% kernel / faults: 17043 minor 3 major
 10% 20267/android.process.media: 8.4% user + 1.7% kernel / faults: 7317 minor 29 major

  ..........

+0% 4864/kworker/3:2: 0% user + 0% kernel
55% TOTAL: 41% user + 11% kernel + 3.3% iowait + 0.3% softirq

Load:爲cpu的平均負載,上面的3個值代表:在某一時刻的前一分鐘、五分鐘、十五分鐘的CPU平均負載;

以上日誌中的三個值分別是19.89 / 21.61 / 22.07,通常關注5/15分鐘的平均負載,因爲1分鐘的平均負載太頻繁,一瞬間的高併發就會導致該值的大幅度改變。

Linux 的系統負載指運行隊列的平均長度,也就是等待 CPU 的平均進程數;相應的cpu的平均負載,也可以通過如下命令抓取:

XXXXX:/ $ cat /proc/loadavg
     18.04 17.04 10.27 1/1831 8606

上述輸出中每個值的含義依次爲:

  • lavg_1 (18.04)      1-分鐘平均負載

  • lavg_5 (17.04)      5-分鐘平均負載

  • lavg_15(10.27)     15-分鐘平均負載

  • nr_running (1)    在採樣時刻,運行隊列的任務的數目

  • nr_threads (1831)  在採樣時刻,系統中活躍的任務的個數(不包括運行已經結束的任務)

  • last_pid(8606)   最大的pid值,包括輕量級進程,即線程。

2.內存信息查看

當ANR發生時,會生成db文件;其中DUMPSYS_MEMINFO 會包含 dump menfinfo的信息。

Total RAM: 2,866,932K (status normal)
Free RAM: 1,028,615K ( 755,567K cached pss + 229,448K cached kernel + 43,600K free)
Used RAM: 2,246,972K (1,923,460K used pss + 323,512K kernel)
Lost RAM: -37,629K
ZRAM: 272,520K physical used for 805,976K in swap (1,048,572K total swap)
Tuning: 256 (large 512), oom 322,560K, restore limit 107,520K (high-end-gfx)

其實MTK已經將總的、可用的內存打印出來了。可是很多人依然以 SYS_MEMORY_INFO中MemFree 很低爲理由,歸爲低內存導致的anr,這其實是個誤區;

如MTKZ抓取的Log打印,系統可用的內存空間是 = MemFree + Cached。

主要的幾個參數的註釋:

MemTotal: 2866932 kB          //所有可用RAM大小
MemFree: 19524 kB              //系統留着未使用的內存
MemAvailable: 756212 kB     ////對應用來說可使用的內存,包含cache+buffer
Buffers: 24620 kB                  //用來給文件做緩衝區的大小
Cached: 713632 kB              //被高速緩衝存儲器(cache memory)用的內存的大小
SwapCached: 8876 kB         //交換空間的大小已經被交換出來的內存
Active: 807600 kB                 //在活躍使用中的緩衝或高速緩衝存儲器頁面文件的大小
Inactive: 810108 kB              //在不經常使用中的緩衝或高速緩衝存儲器頁面文件的大小
Active(anon): 455744 kB
Inactive(anon): 457436 kB
Active(file): 351856 kB
Inactive(file): 352672 kB

Shmem: 1296 kB
Slab: 199004 kB                      //內核數據結構緩存的大小,可以減少申請和釋放內存帶來的消耗

SReclaimable: 62400 kB          //可收回Slab的大小 
SUnreclaim: 136604 kB          //不可收回Slab的大小
KernelStack: 44672 kB

VmallocTotal:   263061440 kB   //可以vmalloc虛擬內存大小

當然,如果你還想看看具體那個進程佔的內存多;可以通過如下的命令查看:

C:\XXXXXXX>adb shell procrank

  PID       Vss            Rss          Pss          Uss         Swap    PSwap    USwap   ZSwap  cmdline

  866  4660800K  310712K  140013K   94212K     288K     288K     288K      70K   system_server

 1816  4387828K  196264K  124524K  121964K       0K       0K       0K         0K      com.transsion.faceid

 1164  4495888K  235400K  105050K   89856K       0K       0K        0K          0K     com.android.systemui

22479  1826744K  171424K   85793K   63544K       0K       0K        0K         0K      com.android.vending

14968 4442376K  201732K   77360K   64520K       0K        0K         0K          0K      com.android.settings

•VSS- Virtual Set Size 虛擬耗用內存(包含共享庫佔用的內存)

•RSS- Resident Set Size 實際使用物理內存(包含共享庫佔用的內存)

•PSS- Proportional Set Size 實際使用的物理內存(比例分配共享庫佔用的內存)

•USS- Unique Set Size 進程獨自佔用的物理內存(不包含共享庫佔用的內存)

•一般來說內存佔用大小有如下規律:VSS >= RSS >= PSS >= USS

 

先上一個報錯的anr 觸摸無響應的log 信息。


01-01 19:00:49.033 779 871 I AnrManager: startAnrDump
01-01 19:00:49.033 779 871 I AnrManager: isANRFlowSkipped() AnrFlow = 0
01-01 19:00:49.034 779 871 I AnrManager: startAnrDump isSystemApp?true, isUserAMonkey?false ProcessRecord{343fdb0 1267:com.google.android.setupwizard/u0a30}
01-01 19:00:49.034 779 871 I AnrManager: enableTraceLog: false
01-01 19:00:49.042 779 871 I AnrManager: startAsyncDump: AnrDumpRecord{ Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 7. Wait queue head age: 5513.7ms.) ProcessRecord{343fdb0 1267:com.google.android.setupwizard/u0a30} IsCompleted:false IsCancelled:false }
01-01 19:00:49.045 779 871 I AnrManager: appNotResponding-got this lock: ProcessRecord{343fdb0 1267:com.google.android.setupwizard/u0a30} Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 7. Wait queue head age: 5513.7ms.),shuttingDown: false,notResponding: false,crashing: false
01-01 19:00:49.045 779 871 I AnrManager: dumpAnrDebugInfo begin: AnrDumpRecord{ Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 7. Wait queue head age: 5513.7ms.) ProcessRecord{343fdb0 1267:com.google.android.setupwizard/u0a30} IsCompleted:false IsCancelled:false }, isAsyncDump = false
01-01 19:00:49.046 779 871 I AnrManager: dumpAnrDebugInfoLocked: AnrDumpRecord{ Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 7. Wait queue head age: 5513.7ms.) ProcessRecord{343fdb0 1267:com.google.android.setupwizard/u0a30} IsCompleted:false IsCancelled:false }, isAsyncDump = false
01-01 19:00:49.127 779 7826 I AnrManager: sys/kernel/debug/binder/timeout_log isn't exist
01-01 19:00:49.176 779 871 I AnrManager: dumpStackTraces begin!
01-01 19:00:49.546 779 890 I AnrManager: START_ANR_DUMP_MSG: AnrDumpRecord{ Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 7. Wait queue head age: 5513.7ms.) ProcessRecord{343fdb0 1267:com.google.android.setupwizard/u0a30} IsCompleted:false IsCancelled:false }
01-01 19:00:49.547 779 890 I AnrManager: dumpAnrDebugInfo begin: AnrDumpRecord{ Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 7. Wait queue head age: 5513.7ms.) ProcessRecord{343fdb0 1267:com.google.android.setupwizard/u0a30} IsCompleted:false IsCancelled:false }, isAsyncDump = true
01-01 19:01:06.185 779 871 I AnrManager: dumpStackTraces end!
01-01 19:01:06.367 779 871 I AnrManager: ANR in com.google.android.setupwizard (com.google.android.setupwizard/.account.KidPostSetupWrapper), time=325984
01-01 19:01:06.367 779 871 I AnrManager: Reason: Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 7. Wait queue head age: 5513.7ms.)
01-01 19:01:06.367 779 871 I AnrManager: Load: 28.9 / 20.05 / 9.04
01-01 19:01:06.367 779 871 I AnrManager: Android time :[2018-01-01 12:01:06.19] [343.149]
01-01 19:01:06.367 779 871 I AnrManager: CPU usage from 279ms to -11697ms ago (2018-01-01 12:00:48.754 to 2018-01-01 12:01:00.730):
01-01 19:01:06.367 779 871 I AnrManager: 91% 779/system_server: 63% user + 27% kernel / faults: 25605 minor 100 major
01-01 19:01:06.367 779 871 I AnrManager: 43% 1026/com.android.systemui: 35% user + 8% kernel / faults: 15881 minor 52 major
01-01 19:01:06.367 779 871 I AnrManager: 27% 6587/com.google.android.gms: 23% user + 4.4% kernel / faults: 13386 minor 87 major
01-01 19:01:06.367 779 871 I AnrManager: 21% 375/surfaceflinger: 11% user + 9.6% kernel / faults: 530 minor 2 major
01-01 19:01:06.367 779 871 I AnrManager: 20% 1157/com.android.phone: 16% user + 4% kernel / faults: 8787 minor 14 major

.......

 

另外一種 :11-05 13:40:49.534 951 974 I am_anr : [0,951,system,818462217,Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)]

我們從打印的信息網上推,一步一步從哪裏開始即何時出發。

 

1 anr 的抓取流程圖 :

這個詳細的沒有仔細看,簡單的過一下代碼 :

 

在 AppErrors.java 的 appNotResponding 中

 

最後調到 AnrManagerService 的 startAnrDump () 的方法 ,開始抓取信息。 代碼太多不截取出來了。    

 

繼續往上查看 

 

  

繼續查看 JNI 下的 com_android_server_input_InputManagerService.cpp                                                                -------------這裏還要看一下啓動

 

 

 

 

 

 

 

 

DEFAULT_INPUT_DISPATCHING_TIMEOUT    這個時間是5s.     currentTime  是傳遞過來的,所以我們看下記錄這個 currentTime 從什麼時候開始計時的。 

這裏再往前調用這個方法的地方有三處 :

我們分別往前看吧 :

第一處 :

 

這裏第一處的調用可以看到 已經有一個按鍵無響應的事件的原因了 :

"Waiting because no window has focus but there is a "
"focused application that may eventually add a window "
"when it finishes starting up.

if (mFocusedWindowHandle == NULL) {           
if (mFocusedApplicationHandle != NULL) {          -------------- 備註 :這裏還要再補充研究  暫時先過總體的流程。

}

應用已啓動,但是窗口還沒獲取到焦點。

然後看一下 :

reason = checkWindowReadyForMoreInputLocked(currentTime,
mFocusedWindowHandle, entry, "focused");

這段代碼太長,但是註釋也比較重要,就沒有刪除註釋 直接截取的。 

 

這裏我們從上往下 :

1 窗口是在paused 狀態 

StringPrintf("Waiting because the %s window is paused.", targetType);   

這個 targetType   是 focused    因爲是     findFocusedWindowTargetsLocked

2 窗口未連接

3 窗口連接已死亡

4 窗口連接已滿

5 按鍵事件,輸出隊列或事件等待隊列不爲空

6 非按鍵事件,事件等待隊列不爲空且頭事件分發超時500ms

 

第二處是 

findTouchedWindowTargetsLocked裏面 

按鍵事件無響應的的原因 解析完了。  

 

 

 

 

這個是native 層的調用到 InputManagerService  的流程圖。但是前面的事件處理,已經需要慢慢仔細的查看了。  我們先梳理好這個主線。  事件派發的流程 在抓緊事件查看梳理,不然部分條件還是沒能整明白。

 

總結 :

        InputDisapcther    把事件  觸摸事件MotionEntry  按鍵事件  Keyevent     然後分別處理,在處理的過程中 在上次事件沒有處理完成,下一次事件 上報後檢查上次事件的的完成是否結束,超出5s呢就開始上報ANR。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章