Android的死機、重啓問題分析方法

原文鏈接:https://blog.csdn.net/ffmpeg4976/article/details/48663985

目錄

 

1.     死機現象

1.1      死機定義

1.2      死機表現

1. 系統簡圖

2. 可能死機的原因

2.      死機分析數據

Backtrace 

系統運行環境

程序執行環境

其他的一些資訊

3.      幾種典型的異常情況

3.1       Deadlock

3.2       執行JNI native code 後一直不見返回

4.     死機運行環境分析

4.1       系統運行環境

4.2       CPU Usage

top

systrace

Kernelcore status

4.3       Memory Usage

4.4       Storage Usage

5.     進程運行環境分析

5.1       系統運行環境

5.2       Java 運行環境分析

5.3       Kernel 運行環境分析

6.     死機問題場景

7.     死機問題現場分析

7.1       死機現場分析手法

7.2       基本分析流程

7.3       Test Phone Usage

7.4       USB/ADB Debug Hang

7.4.1 USB/ADB Debug 準備

7.4.2 USB/ADB 連接分析

7.4.3 機器狀態基本檢測

7.5       UART Debug

7.6       確認死機的模塊

Input Driver-Input System

system-server logic

Display logic

8.     無現場猜測分析

8.1       無場景猜測與分析

8.2       死機資訊的完整紀錄

8.3       死機Log 分析

8.4死機Log 分析, trace 輔助

9.     死機日誌抓取

9.1       當機器死機時,建議使用下面腳本抓取資訊:

9.2       當機器重啓後,可以使用下面腳本抓取:

10.2   死機如何轉換成重啓

10.3  死機VS重啓


 

1.     死機現象

1.1      死機定義

當手機長時間無法再被用戶控制操作時,我們稱爲死機。在這裏我們強調長時間,如果是短時間,歸結爲性能問題。

1.2      死機表現

* 用戶操作手機無任何響應,如觸摸屏幕,按鍵操作等。

* 手機屏幕黑屏,無法點亮屏幕。

* 手機界面顯示內容和用戶輸入不相干。

1. 系統簡圖

當用戶對手機進行操作時,對應的數據流將是下面一個概括的流程圖

 

* HW 如傳感器,觸摸屏(TP),物理按鍵(KP)等感知到用戶操作後,觸發相關的中斷(ISR)傳遞給Kernel,Kernel相關的driver 對這些中斷進行處理後,轉化成標準的InputEvent。 

* UserSpace 的System Server中的Input System則持續監聽Kernel傳遞上來的原始InputEvent,對其進行進一步的處理後,變成上層APP可直接處理的Input Event,如button點擊,長按,滑動等等。

* APP 對相關的事件進行處理後,請求更新相關的邏輯界面,而這個則由System Server中的WMS 等來負責。

* 相關的邏輯界面更新後,則會請求SurfaceFlinger來產生FrameBuffer數據,SurfaceFlinger則會利用GPU 等來計算生成。

* DisplaySystem/Driver 則會將FrameBuffer中的數據更新顯示出來,這樣用戶才能感知到他的操作行爲。

2. 可能死機的原因

原則上上面流程中,每一步出現問題,都可能引發死機問題。大的方面講,可以分成硬件HW和軟件SW兩個層次,硬件HW不在我們的範圍之內。

軟件SW上,死機的原因可以分成兩種:

(1). 邏輯行爲異常

 ** 邏輯判斷錯誤

 ** 邏輯設計錯誤

 (2). 邏輯卡頓(block)

 * 死循環 (Deadloop)

 * 死鎖 (Deadlock)

 從具體的原因上將,可以進一步分成:

(1). InputDriver

* 無法接收HW的中ISR,產生原始的InputEvent或者產生的InputEvent異常。

分析死機、觸屏無響應的問題的時候,第一步要先看看有沒有inputEvent上來,即有沒有報點,各個平臺inputEvent的設備節點都不一樣,可以通過下面方法獲取:

adb shell getevent

這個命令下下去以後會在屏幕上輸出當前設備的節點,可從name一行判斷哪一個是TW,當然也可以在此時直接在屏幕上觸摸看有沒有時間上報,正常情況如下:

 

可以看出event2是觸摸事件。

異常情況下觸摸是沒有事件上報的。

當然也可以直接下adb shell getevent /dev/input/event2檢查。

(2). InputSystem

 無法監聽Kernel傳遞上來的原始InputEvent,或者轉換與傳遞異常。

(3). SystemLogic

 無法正常響應InputSystem傳遞過來的InputEvent,或者響應出錯。

(4).WMS/Surfaceflinger 行爲異常

 WMS/ Surfaceflinger 無法正確的對Window進行疊加轉換

(5).Display System

 無法更新Framebuffer數據,或者填充的數據錯誤

(6). LCMDriver

無法將Framebuffer數據顯示在LCM上

 對應硬件HW異常,經常見得的情況有:

*Power 

* Clock

* Memory& Memory Controller

* Fail IC

2.      死機分析數據

死機分析,同樣需要獲取第一手的資料,方可分析問題.那麼哪些數據可以用來分析死機呢?

大概的講,可以分成空間數據和時間數據。空間數據,即當時現場環境,如有哪些process在運行,CPU 的執行情況,memory 的利用情況,以及具體的process的memory 數據等。時間數據,即行爲上的連續數據,比如某個Process在一段時間內執行了哪些操作,某段時間內CPU利用率的變化等。通常時空都是交融的,對應我們抓取log時往往也是。 

Backtrace 

Backtrace 又分成Java backtrace,Native Backtrace,Kernel Backtrace。它是分析死機的非常重要的手段,藉助Backtrace,我們可以快速的知道,對應的process/thread在當時正在執行哪些動作,卡住哪裏等。可以非常直觀的分析死機現場。

1 Java Backtrace

從Java Backtrace,我們可以知道當時Process的虛擬機執行狀態。 JavaBacktrace依靠SignalCatcher來抓取。

Googledefault: SignalCatcher catchs SIGQUIT(3), and thenprint the java backtrace to /data/anr/trace.txt

MTKEnhance:  SignalCatcher catchs SIGSTKFLT(16), and thenprint the java backtrace to /data/anr/mtktrace.txt( After 6577.SP/ICS2.MP)

可以通過修改系統屬性dalvik.vm.stack-trace-file改變trace文件路徑, 默認路徑爲/data/anr/traces.txt

1.1       抓取的方式

一般進程出現無響應的問題,Android系統會發送SIGQUIT(3)信號給該進程,收到這個信號會,進程會將當前的調用棧打印在trace.txt文件裏。

手動抓取進程的Backtrace方法如下:

adb remount

adb shell chmod 0777 data/anr

adb shell kill -3 pid

adb pull /data/anr

 1.2JavaBacktrace 解析

下面是一小段system server的java backtrace的開始

----- pid 682 at 2015-07-30 18:04:53 -----

Cmd line: system_server

JNI: CheckJNI is off; workarounds are off;pins=4; globals=1484 (plus 50 weak)

DALVIK THREADS:

"main" prio=5 tid=1 NATIVE

  | group="main" sCount=1dsCount=0 obj=0x4193fde0 self=0x418538f8

  | sysTid=682 nice=-2 sched=0/0cgrp=apps handle=1074835940

  | state=S schedstat=( 4785871820626265263191 44902 ) utm=4074 stm=711 core=0

  at android.os.MessageQueue.nativePollOnce(NativeMethod)

  at android.os.MessageQueue.next(MessageQueue.java:138)

  at android.os.Looper.loop(Looper.java:150)

  at com.android.server.ServerThread.initAndLoop(SystemServer.java:1468)

  at com.android.server.SystemServer.main(SystemServer.java:1563)

  at java.lang.reflect.Method.invokeNative(NativeMethod)

  at java.lang.reflect.Method.invoke(Method.java:515)

  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)

  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)

  at dalvik.system.NativeStart.main(NativeMethod)

  我們一行一行來解析.

0# 最開始是 -----PID at Time  然後接着 Cmd line: process name

1#  the backtrace header: dvm thread :“DALVIK THREADS:”

 2# thread name, java thread Priority, [daemon], DVM thread id, DVM thread status.

 "main"  -> mainthread -> activity thread

 prio  -> java threadpriority default is 5, (nice =0, linux thread priority 120), domain is [1,10]

 DVMthread id, NOT linux thread id

 DVM thread Status:

  ZOMBIE,  RUNNABLE, TIMED_WAIT, MONITOR, WAIT, INITALIZING,STARTING, NATIVE, VMWAIT, SUSPENDED,UNKNOWN

  "main" prio=5 tid=1NATIVE

 3# DVM thread status 

 group: default is “main”

   Compiler,JDWP,Signal Catcher,GC,FinalizerWatchdogDaemon,FinalizerDaemon,ReferenceQueueDaemonare system group

 sCount:  thread suspend count

 dsCount: thread dbg suspend count

 obj:     threadobj address

 Sef:  thread point address

 group="main" sCount=1dsCount=0 obj=0x4193fde0 self=0x418538f8

#5 Linux thread status

 sysTId:  linux thread tid

 Nice: linux thread nice value

 sched: cgroup policy/gourp id

 cgrp:  c group  

 handle:  handle address

 sysTid=682 nice=-2 sched=0/0cgrp=apps handle=1074835940

 #6 CPU Schedstat

 Schedstat (Run CPU Clock/ns, Wait CPU Clock/ns,  Slice times)

 utm: utime, user space time(jiffies)

 stm: stime, kernel space time(jiffies)

 Core now running in cpu.

 state=S schedstat=( 4785871820626265263191 44902 ) utm=4074 stm=711 core=0

 #7-more CallStack

1.3 幾種常見的java backtrace

1.3.1ActivityThread 正常狀態的Backtrace

MessageQueue is empty, and thread wait fornext message.

 "main" prio=5 tid=1 NATIVE

   | group="main"sCount=1 dsCount=0 obj=0x4193fde0 self=0x418538f8

   | sysTid=11559 nice=0sched=0/0 cgrp=apps/bg_non_interactive handle=1074835940

   | state=S schedstat=(2397315020 9177261498 7975 ) utm=100 stm=139 core=1

   at android.os.MessageQueue.nativePollOnce(NativeMethod)

   at android.os.MessageQueue.next(MessageQueue.java:138)

   at android.os.Looper.loop(Looper.java:150)

   at android.app.ActivityThread.main(ActivityThread.java:5299)

   at java.lang.reflect.Method.invokeNative(NativeMethod)

   at java.lang.reflect.Method.invoke(Method.java:515)

   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)

   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)

   at dalvik.system.NativeStart.main(NativeMethod)

1.3.2 JavaBacktrace Monitor case

SynchronizedLock:等待同步鎖時的backtrace.

 "AnrMonitorThread" prio=5tid=24 MONITOR

   | group="main"sCount=1 dsCount=0 obj=0x41fd80c8 self=0x551ac808

   | sysTid=711 nice=0 sched=0/0cgrp=apps handle=1356369328

   | state=S schedstat=(8265377638 4744771625 6892 ) utm=160 stm=666 core=0

   at com.android.server.am.ANRManager$AnrDumpMgr.dumpAnrDebugInfoLocked(SourceFile:~832)

   - waiting to lock<0x42838968> (a com.android.server.am.ANRManager$AnrDumpRecord) held bytid=20 (ActivityManager)

   at com.android.server.am.ANRManager$AnrDumpMgr.dumpAnrDebugInfo(SourceFile:824)

   at com.android.server.am.ANRManager$AnrMonitorHandler.handleMessage(SourceFile:220)

   at android.os.Handler.dispatchMessage(Handler.java:110)

   at android.os.Looper.loop(Looper.java:193)

   at android.os.HandlerThread.run(HandlerThread.java:61)

1.3.3 執行JNI code未返回,狀態是native的情況

 "WifiP2pService" prio=5tid=37 NATIVE

   | group="main"sCount=1 dsCount=0 obj=0x427a9910 self=0x55f088d8

   | sysTid=734 nice=0 sched=0/0cgrp=apps handle=1443230288

   | state=S schedstat=( 91121772135245305 170 ) utm=7 stm=2 core=1

   #00  pc 00032700 /system/lib/libc.so (epoll_wait+12)

   #01  pc 000105e3 /system/lib/libutils.so (android::Looper::pollInner(int)+94)

   #02  pc 00010811 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92)

   #03  pc 0006c96d /system/lib/libandroid_runtime.so(android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22)

   #04  pc 0001eacc /system/lib/libdvm.so (dvmPlatformInvoke+112)

   #05  pc 0004fed9 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+484)

   #06  pc 00027ea8 /system/lib/libdvm.so

   #07  pc 0002f4b0 /system/lib/libdvm.so (dvmMterpStd(Thread*)+76)

   #08  pc 0002c994 /system/lib/libdvm.so (dvmInterpret(Thread*, Methodconst*, JValue*)+188)

   #09  pc 000632a5 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Methodconst*, Object*, bool, JValue*,std::__va_list)+340)

   #10  pc 000632c9 /system/lib/libdvm.so (dvmCallMethod(Thread*, Methodconst*, Object*, JValue*, ...)+20)

   #11  pc 00057961 /system/lib/libdvm.so

   #12  pc 0000dd40 /system/lib/libc.so (__thread_entry+72)

   at android.os.MessageQueue.nativePollOnce(NativeMethod)

   at android.os.MessageQueue.next(MessageQueue.java:138)

   at android.os.Looper.loop(Looper.java:150)

   at android.os.HandlerThread.run(HandlerThread.java:61)

1.3.4 執行object.wait等待狀態

 "AsyncTask #1" prio=5tid=33 WAIT

   | group="main"sCount=1 dsCount=0 obj=0x427a8480 self=0x56036b40

   | sysTid=733 nice=10sched=0/0 cgrp=apps/bg_non_interactive handle=1443076000

   | state=S schedstat=(1941480839 10140523154 4229 ) utm=119 stm=75 core=0

   at java.lang.Object.wait(NativeMethod)

   - waiting on<0x427a8618> (a java.lang.VMThread) held by tid=33 (AsyncTask #1)

   at java.lang.Thread.parkFor(Thread.java:1212)

   at sun.misc.Unsafe.park(Unsafe.java:325)

   at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)

   at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2017)

   at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:410)

   at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1035)

   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1097)

   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)

   at java.lang.Thread.run(Thread.java:848)

1.3.5Suspend 狀態,通常表明是抓取backtrace時,當時還正在執行java代碼,被強制suspend的情況

 "FileObserver" prio=5tid=23 SUSPENDED

   | group="main"sCount=1 dsCount=0 obj=0x41fd1dc8 self=0x551abda0

   | sysTid=710 nice=0 sched=0/0cgrp=apps handle=1427817920

   | state=S schedstat=(130152222 399783851 383 ) utm=9 stm=4 core=0

   #00  pc 000329f8 /system/lib/libc.so (__futex_syscall3+8)

   #01  pc 000108cc /system/lib/libc.so (__pthread_cond_timedwait_relative+48)

   #02  pc 0001092c /system/lib/libc.so (__pthread_cond_timedwait+64)

   #03  pc 00055a93 /system/lib/libdvm.so

   #04  pc 0005614d  /system/lib/libdvm.so(dvmChangeStatus(Thread*, ThreadStatus)+34)

   #05  pc 0004ae7f /system/lib/libdvm.so

   #06  pc 0004e353 /system/lib/libdvm.so

   #07  pc 000518d5 /system/lib/libandroid_runtime.so

   #08  pc 0008af9f /system/lib/libandroid_runtime.so

   #09  pc 0001eacc /system/lib/libdvm.so (dvmPlatformInvoke+112)

   #10  pc 0004fed9 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+484)

   #11  pc 00027ea8 /system/lib/libdvm.so

   #12  pc 0002f4b0 /system/lib/libdvm.so (dvmMterpStd(Thread*)+76)

   #13  pc 0002c994 /system/lib/libdvm.so (dvmInterpret(Thread*, Methodconst*, JValue*)+188)

   #14  pc 000632a5 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Methodconst*, Object*, bool, JValue*, std::__va_list)+340)

   #15  pc 000632c9 /system/lib/libdvm.so (dvmCallMethod(Thread*, Methodconst*, Object*, JValue*, ...)+20)

   #16  pc 00057961 /system/lib/libdvm.so

   #17  pc 0000dd40 /system/lib/libc.so (__thread_entry+72)

   at android.os.FileObserver$ObserverThread.observe(NativeMethod)

   at android.os.FileObserver$ObserverThread.run(FileObserver.java:88)

2 Native Backtrace

 2.1Native Backtrace 抓取方式

  2.1.1添加代碼直接抓取

Google 默認提供了CallStack API,請參考

system/core/include/libutils/CallStack.h 

system/core/libutils/CallStack.cpp

可快速打印單個線程的backtrace.

2.1.2 自動抓取

Natice層的進程發生異常後一般都在/data/tombstones目錄下生成文件(墓碑文件),該文件描述了該進程當前的Backtrace,不過是鏈接地址,需要進行解析。

 2.1.3利用debuggerd抓取

MTK 已經制作了一個利用debuggerd抓取Native backtrace的tool RTT(Runtime Trace),對應的執行命令是:

rtt builttimestamp (Apr 18 2014 15:36:21)

USAGE : rtt[-h] -f function -p pid [-t tid]

  -ffuncion : current support functions:

                bt  (Backtrace function)

  -ppid     : pid to trace

  -ttid     : tid to trace

  -nname    : process name to trace

 -h         : help menu

 2.2解析Native Backtrace

你可以使用GDB,或者addr2line等 tool 來解析抓回的Native Backtrace,從而知道當時正在執行的native代碼,

arm-linux-androideabi-addr2line-f -C -e symbols address

公司將addr2line封裝後實現了一套解析NativeBacktrace(show Stack)。參考下文

3 Kernel Backtrace

 3.1Kernel Backtrace 抓取方式

3.1.1 運行時抓取

* AEE/RTT 工具

* ProcSystem

  catproc/pid/task/tid/stack

*Sysrq-trigger

 adbshell cat proc/kmsg > kmsg.txt

 adbshell "echo 8 > proc/sys/kernel/printk“ //修改printk loglevel

 adbshell "echo t > /proc/sysrq-trigger“ //打印所有的backtrace

 adbshell "echo w > /proc/sysrq-trigger“//打印'-D' status'D'的 process

* KDB

 Longpress volume UP and DOWN more then 10s

 btp            <pid>                

 Displaystack for process <pid>

 bta            [DRSTCZEUIMA]        

 Displaystack all processes

 btc                                  

 Backtracecurrent process on each cpu

 btt            <vaddr>              

 Backtraceprocess given its struct task add

3.1.2 添加代碼直接抓取

* #include<linux/sched.h>

 當前thread:  dump_stack();

 其他thread:  show_stack(task, NULL);

3.2Process/Thread 狀態

 "R(running)",  /*  0 */

 "S(sleeping)",  /*  1 */

 "D(disk sleep)", /*   2*/

 "T(stopped)",  /*  4 */

 "t(tracing stop)", /*   8*/

 "Z(zombie)",  /* 16 */

 "X(dead)",  /* 32 */

 "x(dead)",  /* 64 */

 "K(wakekill)",  /* 128 */

 "W(waking)",  /* 256 */

通常一般的Process處於的狀態都是S(sleeping),而如果一旦發現處於如D (disksleep), T (stopped), Z (zombie)等就要認真審查。

系統運行環境

客觀的反應系統的執行環境,通常包括如CPU利用率,Memory 使用情況, Storage 剩餘情況等。這些資料也非常重要,比如可以快速的知道,當時是否有Process在瘋狂的執行,當時是不是處於嚴重的low memory情況, Storage是否有耗盡的情況發生等。

程序執行環境

客觀的反應當時某個程序(Kernel也可以看成一個程序)的執行現場,此類資訊通常包括如process的coredump, java heap prof, kernel的memory dump 等。完整的執行環境,我們可以快速的知道當時具體的變量的值,寄存器值等,可以精細的分析問題。

其他的一些資訊

這些資訊相對來說,比較零散了,如通常的LOG,一些debug命令的結果數據等。

3.      幾種典型的異常情況

3.1       Deadlock

下面這個case可以看到PowerManagerService, ActivityManager, WindowManager相互之間發生deadlock。

"PowerManagerService" prio=5tid=25 MONITOR

  | group="main" sCount=1dsCount=0 obj=0x42bae270 self=0x6525d5c0

  | sysTid=913 nice=0 sched=0/0cgrp=apps handle=1696964440

  | state=S schedstat=( 508893941110237027338 34016 ) utm=232 stm=276 core=2

  atcom.android.server.am.ActivityManagerService.bindService(ActivityManagerService.java:~14079)

  - waiting to lock <0x42aa0f78> (acom.android.server.am.ActivityManagerService) held by tid=16 (ActivityManager)

  atandroid.app.ContextImpl.bindServiceCommon(ContextImpl.java:1665)

  atandroid.app.ContextImpl.bindService(ContextImpl.java:1648)

  atcom.android.server.power.PowerManagerService.bindSmartStandByService(PowerManagerService.java:4090)

  atcom.android.server.power.PowerManagerService.handleSmartStandBySettingChangedLocked(PowerManagerService.java:4144)

  at com.android.server.power.PowerManagerService.access$5600(PowerManagerService.java:102)

  atcom.android.server.power.PowerManagerService$SmartStandBySettingObserver.onChange(PowerManagerService.java:4132)

  atandroid.database.ContentObserver$NotificationRunnable.run(ContentObserver.java:181)

  atandroid.os.Handler.handleCallback(Handler.java:809)

  atandroid.os.Handler.dispatchMessage(Handler.java:102)

  atandroid.os.Looper.loop(Looper.java:139)

  atandroid.os.HandlerThread.run(HandlerThread.java:58)

  "ActivityManager" prio=5tid=16 MONITOR

  | group="main" sCount=1dsCount=0 obj=0x42aa0d08 self=0x649166b0

  | sysTid=902 nice=-2 sched=0/0cgrp=apps handle=1687251744

  | state=S schedstat=( 3936088146025703061063 69675 ) utm=1544 stm=2392 core=2

  at com.android.server.wm.WindowManagerService.setAppVisibility(WindowManagerService.java:~4783)

  - waiting to lock <0x42d17590> (ajava.util.HashMap) held by tid=12 (WindowManager)

  atcom.android.server.am.ActivityStack.stopActivityLocked(ActivityStack.java:2432)

  at com.android.server.am.ActivityStackSupervisor.activityIdleInternalLocked(ActivityStackSupervisor.java:2103)

  atcom.android.server.am.ActivityStackSupervisor$ActivityStackSupervisorHandler.activityIdleInternal(ActivityStackSupervisor.java:2914)

  at com.android.server.am.ActivityStackSupervisor$ActivityStackSupervisorHandler.handleMessage(ActivityStackSupervisor.java:2921)

  atandroid.os.Handler.dispatchMessage(Handler.java:110)

  atandroid.os.Looper.loop(Looper.java:147)

  atcom.android.server.am.ActivityManagerService$AThread.run(ActivityManagerService.java:2112)

  "WindowManager" prio=5tid=12 MONITOR

  | group="main" sCount=1dsCount=0 obj=0x42a92550 self=0x6491dd48

  | sysTid=898 nice=-4 sched=0/0cgrp=apps handle=1687201104

  | state=S schedstat=( 60734070955 41987172579219755 ) utm=4659 stm=1414 core=1

  atcom.android.server.power.PowerManagerService.setScreenBrightnessOverrideFromWindowManagerInternal(PowerManagerService.java:~3207)

  - waiting to lock <0x42a95140> (ajava.lang.Object) held by tid=25 (PowerManagerService)

  atcom.android.server.power.PowerManagerService.setScreenBrightnessOverrideFromWindowManager(PowerManagerService.java:3196)

  atcom.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLockedInner(WindowManagerService.java:9686)

  atcom.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLockedLoop(WindowManagerService.java:8923)

  atcom.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLocked(WindowManagerService.java:8879)

  at com.android.server.wm.WindowManagerService.access$500(WindowManagerService.java:170)

  atcom.android.server.wm.WindowManagerService$H.handleMessage(WindowManagerService.java:7795)

  atandroid.os.Handler.dispatchMessage(Handler.java:110)

  at android.os.Looper.loop(Looper.java:147)

  atandroid.os.HandlerThread.run(HandlerThread.java:58)

3.2       執行JNI native code 後一直不見返回

"main" prio=5 tid=1 NATIVE

  | group="main" sCount=1dsCount=0 obj=0x41bb3d98 self=0x41ba2878

  | sysTid=814 nice=-2 sched=0/0cgrp=apps handle=1074389380

  | state=D schedstat=( 2204889092819526803112 32612 ) utm=1670 stm=534 core=0

  (native backtrace unavailable)

  at android.hardware.SystemSensorManager$BaseEventQueue.nativeDisableSensor(NativeMethod)

  at android.hardware.SystemSensorManager$BaseEventQueue.disableSensor(SystemSensorManager.java:399)

  at android.hardware.SystemSensorManager$BaseEventQueue.removeAllSensors(SystemSensorManager.java:325)

  at android.hardware.SystemSensorManager.unregisterListenerImpl(SystemSensorManager.java:194)

  at android.hardware.SensorManager.unregisterListener(SensorManager.java:560)

  at com.android.internal.policy.impl.WindowOrientationListener.disable(WindowOrientationListener.java:139)

  at com.android.internal.policy.impl.PhoneWindowManager.updateOrientationListenerLp(PhoneWindowManager.java:774)

  at com.android.internal.policy.impl.PhoneWindowManager.screenTurnedOff(PhoneWindowManager.java:4897)

  at com.android.server.power.Notifier.sendGoToSleepBroadcast(Notifier.java:518)

  at com.android.server.power.Notifier.sendNextBroadcast(Notifier.java:434)

  at com.android.server.power.Notifier.access$500(Notifier.java:63)

  at com.android.server.power.Notifier$NotifierHandler.handleMessage(Notifier.java:584)

  at android.os.Handler.dispatchMessage(Handler.java:110)

  at android.os.Looper.loop(Looper.java:193)

  at com.android.server.ServerThread.initAndLoop(SystemServer.java:1436)

  at com.android.server.SystemServer.main(SystemServer.java:1531)

  at java.lang.reflect.Method.invokeNative(NativeMethod)

  at java.lang.reflect.Method.invoke(Method.java:515)

  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)

  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)

  at dalvik.system.NativeStart.main(NativeMethod)

===>

KERNEL SPACE BACKTRACE, sysTid=814

 [<ffffffff>] 0xffffffff from[<c07e5140>] __schedule+0x3fc/0x950

 [<c07e4d50>]__schedule+0xc/0x950 from [<c07e57e4>] schedule+0x40/0x80

 [<c07e57b0>] schedule+0xc/0x80from [<c07e5ae4>] schedule_preempt_disabled+0x20/0x2c

 [<c07e5ad0>]schedule_preempt_disabled+0xc/0x2c from [<c07e3c3c>]mutex_lock_nested+0x1b8/0x560

 [<c07e3a90>]mutex_lock_nested+0xc/0x560 from [<c05667d8>] gsensor_operate+0x1bc/0x2c0

 [<c0566628>]gsensor_operate+0xc/0x2c0 from [<c0495fa0>] hwmsen_enable+0xa8/0x30c

 [<c0495f04>]hwmsen_enable+0xc/0x30c from [<c0496500>]hwmsen_unlocked_ioctl+0x2fc/0x528

 [<c0496210>]hwmsen_unlocked_ioctl+0xc/0x528 from [<c018ad98>] do_vfs_ioctl+0x94/0x5bc

 [<c018ad10>] do_vfs_ioctl+0xc/0x5bcfrom [<c018b33c>] sys_ioctl+0x7c/0x8c

 [<c018b2cc>]sys_ioctl+0xc/0x8c from [<c000e480>] ret_fast_syscall+0x0/0x40

 [<ffffffff>]  from[<ffffffff>] 

4.     死機運行環境分析

4.1       系統運行環境

客觀的反應系統的執行環境,通常包括如CPU利用率,Memory 使用情況, Storage 剩餘情況等。這些資料也非常重要,比如可以快速的知道,當時是否有Process在瘋狂的執行,當時是不是處於嚴重的low memory情況, Storage是否有耗盡的情況發生等。

4.2       CPU Usage

追查CPU利用率可大體的知道,當時機器是否有Process在瘋狂的運行,當時系統運行是否繁忙。通常死機分析,只需要抓取基本的使用情況即可。下面說一下一般的抓取方式

top

top 可以簡單的查詢Cpu的基本使用情況

Usage: top[ -m max_procs ] [ -n iterations ] [ -d delay ] [ -s sort_column ] [ -t ] [ -h]

   -m num  Maximum number of processes to display.

   -n num  Updates to show before exiting.

   -d num  Seconds to wait between updates.

   -s col  Column to sort by (cpu,vss,rss,thr).

   -t      Show threads instead of processes.

   -h      Display this help screen.

注意的是top的CPU% 是按全部CPU 來計算的,如果以單線程來計算,比如當時有開啓4個核心,那麼最多吃到25%。 

個人常見的操作方式如:  top -t -m 5 -n 2

I.E 正常情況

User 2%, System 12%, IOW 0%, IRQ 0%

User 14 + Nice 0 + Sys 67 + Idle 471 + IOW0 + IRQ 0 + SIRQ 2 = 554

  PID   TID PR CPU%S     VSS     RSS PCYUID     Thread          Proc

 2423  2423  1  8% R   2316K   1128K    root    top             top

  270   270 0   1% S   2160K   924K     root    aee_resmon      /system/bin/aee_resmon

  159   159 0   0% D     0K      0K    root     bat_thread_kthr

   3     3  0   0%S      0K     0K     root     ksoftirqd/0

   57    57 0   0% D     0K      0K    root     hps_main

User 1%, System 7%, IOW 0%, IRQ 0%

User 10 + Nice 0 + Sys 41 + Idle 494 + IOW0 + IRQ 0 + SIRQ 0 = 545

  PID   TID PR CPU%S     VSS     RSS PCYUID     Thread          Proc

 2423  2423  1  8% R   2324K   1152K    root    top             top

   57    57 0   0% D     0K      0K    root     hps_main

  242   419 0   0% S   8600K   4540K    shell    mobile_log_d    /system/bin/mobile_log_d

  982   991 0   0% S   4364K   1156K    media_rw sdcard         /system/bin/sdcard

  272   272 0   0% S  30680K   9048K    root    em_svr          /system/bin/em_svr

  從上面可以看出,系統基本運行正常,沒有很吃CPU的進程。

I.E 異常情況

User 59%, System 4%, IOW 2%, IRQ 0%

User 1428 + Nice 0 + Sys 110 + Idle 811 +IOW 67 + IRQ 0 + SIRQ 1 = 2417

  PID   TID PR CPU%S     VSS     RSS PCYUID     Thread          Proc

16132 32195  3  14% R997100K  53492K  bg u0_a60  Thread-1401     com.android.mms

16132 32190  1  14% R997100K  53492K  bg u0_a60  Thread-1400     com.android.mms

16132 32188  2  14% R997100K  53492K  bg u0_a60  Thread-1399     com.android.mms

16132 32187  0  14% R997100K  53492K  bg u0_a60  Thread-1398     com.android.mms

18793 18793  4   1%R   2068K   1020K    shell   top             top

User 67%, System 3%, IOW 7%, IRQ 0%

User 1391 + Nice 0 + Sys 75 + Idle 435 +IOW 146 + IRQ 0 + SIRQ 1 = 2048

  PID   TID PR CPU%S     VSS     RSS PCYUID     Thread          Proc

16132 32195  3  16% R997100K  53492K  bg u0_a60  Thread-1401     com.android.mms

16132 32188  2  16% R997100K  53492K  bg u0_a60  Thread-1399     com.android.mms

16132 32190  0  16% R997100K  53492K  bg u0_a60  Thread-1400     com.android.mms

16132 32187  1  16% R997100K  53492K  bg u0_a60  Thread-1398     com.android.mms

18793 18793  4   2%R   2196K   1284K    shell   top             top

可以明顯的看到,貴司的mms的4個thread都有進入了deadloop,分別佔用了一個cpu core. 同時可以快速抓取他們的java trace, 進一步可以看到當時MMS的四個backtrace,以便快速分析。

"Thread-1401" prio=5 tid=32SUSPENDED JIT

  | group="main" sCount=1dsCount=0 obj=0x4264f860 self=0x7b183558

  | sysTid=32195 nice=0 sched=0/0cgrp=apps/bg_non_interactive handle=2078705952

  | state=S schedstat=( 3284456714198104216273858 383002 ) utm=324720 stm=3725 core=5

  at com.yulong.android.mms.c.f.d(MmsChatDataServer.java:~1095)

  at com.yulong.android.mms.ui.MmsChatActivity$37.run(MmsChatActivity.java:7582)

  at java.lang.Thread.run(Thread.java:841)

"Thread-1400" prio=5 tid=31SUSPENDED JIT

  | group="main" sCount=1dsCount=0 obj=0x41f5d8f0 self=0x7be2a8e8

  | sysTid=32190 nice=0 sched=0/0cgrp=apps/bg_non_interactive handle=2078029504

  | state=S schedstat=( 3284905134412105526230562 382946 ) utm=324805 stm=3685 core=5

  at com.yulong.android.mms.ui.MmsChatActivity$37.run(MmsChatActivity.java:~7586)

  at java.lang.Thread.run(Thread.java:841)

"Thread-1399" prio=5 tid=30SUSPENDED JIT

  | group="main" sCount=1dsCount=0 obj=0x42564d28 self=0x7b0e6838

  | sysTid=32188 nice=0 sched=0/0cgrp=apps/bg_non_interactive handle=2077662640

  | state=S schedstat=( 3288042313685103203810616 375959 ) utm=325143 stm=3661 core=7

  at com.yulong.android.mms.ui.MmsChatActivity$37.run(MmsChatActivity.java:~7586)

  at java.lang.Thread.run(Thread.java:841)

"Thread-1398" prio=5 tid=29SUSPENDED

  | group="main" sCount=1dsCount=0 obj=0x4248e5a8 self=0x7be0d128

  | sysTid=32187 nice=0 sched=0/0cgrp=apps/bg_non_interactive handle=2079251904

  | state=S schedstat=( 3287248372432105116936413 379634 ) utm=325055 stm=3669 core=6

  at com.yulong.android.mms.ui.MmsChatActivity$37.run(MmsChatActivity.java:~7586)

  at java.lang.Thread.run(Thread.java:841)

當時處於suspend,即意味着當時這四個thread正在執行java code,而抓取backtrace時強制將thread suspend。看起來客戶改動所致,並且客戶有Proguard,麻煩客戶自己review代碼。

systrace

ftrace 可以紀錄CPU最爲詳細的執行情況,即linux scheduler的執行情況。通常默認只開啓 sched_switch。 

如何抓取ftrace可以查詢相關的FAQ。

Kernelcore status

有的時候我們需要追查一下,當時Kernel的基本調度情況,以及接收中斷的情況,以判斷當前CPU執行的基本情況是否異常。比如有時候如果某個中斷上來太過頻繁,就容易導致系統運行緩慢,甚至死機。

* CPU Sched status

     adb shell catproc/sched_debug

     Use sysrq-trigger

* CPU interrupts

     adb shell catproc/interrupts

     adb shell catproc/irq/irq_id/spurious

4.3       Memory Usage

MemoryUsage,我們通常會審查,系統當時memory是否足夠,是否處於low memory狀態,是否可能出現因無法申請到memory而卡死的情況。

常見的一些基本信息如下:

* meminfo: basic memory status

adb shell cat proc/meminfo

adb shell cat proc/pid/maps

adb shell cat proc/pid/smaps

* procrank info: all process memory status

adb shell procrank

adb shell procmem pid

adb shell dumpsys meminfo pid

* zoneinfo:

adb shell cat proc/zoneinfo

* buddyinfo:

adb shell cat /proc/buddyinfo

4.4       Storage Usage

查看Storage的情況,通常主要是查詢data分區是否已經刷滿, sdcard是否已經刷滿,剩餘的空間是否足夠。以及是否有產生超大文件等。

通常使用的命令如 df

df

Filesystem              Size     Used     Free  Blksize

/dev                  446.0M   128.0K   445.8M   4096

/sys/fs/cgroup        446.0M    12.0K   445.9M   4096

/mnt/secure           446.0M     0.0K   446.0M   4096

/mnt/asec             446.0M     0.0K   446.0M   4096

/mnt/obb              446.0M     0.0K   446.0M   4096

/system                 1.2G   915.3M   355.5M   4096

/data                   1.1G   136.7M  1010.1M   4096

/cache                106.2M    48.0K   106.2M   4096

/protect_f              4.8M    52.0K     4.8M   4096

/protect_s              4.8M    48.0K     4.8M   4096

/mnt/cd-rom             1.2M     1.2M     0.0K   2048

/mnt/media_rw/sdcard0    4.6G     1.1G     3.4G  32768

/mnt/secure/asec        4.6G     1.1G     3.4G  32768

/storage/sdcard0        4.6G     1.1G     3.4G  32768

以及ls, du 等命令,如du

du -help

usage: du [-H | -L | -P] [-a | -d depth |-s] [-cgkmrx] [file …]

du -LP -d 1

8       ./lost+found

88      ./local

384     ./misc

48      ./nativebenchmark

912     ./nativetest

8       ./dontpanic

13376  ./data

8       ./app-private

8       ./app-asec

129424  ./app-lib

8       ./app

136     ./property

16      ./ssh

116312  ./dalvik-cache

8       ./resource-cache

48      ./drm

8       ./mediadrm

8       ./security

3888    ./nvram

8       ./amit

8       ./acdapi

88      ./@btmtk

32      ./sec

8       ./user

16      ./media

16      ./agps_supl

8       ./anr

8       ./gps_mnl

8       ./nfc_socket

16      ./ccci_cfg

32      ./mdlog

1312    ./system

176     ./recovery

32      ./backup

274688  .

5.     進程運行環境分析

5.1       系統運行環境

當我們懷疑死機問題可能是某個進程出現問題而引發時,通常我們需要對這個進程進行深入的分析,即進程運行環境分析。通常包括分析如,線程狀態,各種變量值,寄存器狀態等。在Android系統中,我們將其劃分成三個層次。

即 Java運行環境分析, Native運行環境分析, Kernel運行環境分析。下面分別說明。

5.2       Java 運行環境分析

我們對於Zygote fork出來的process,如APP以及system_server,都會進行Java運行環境分析。其關鍵是分析Java Heap,以便快速知道某個Java變量的值,以及Java對象的分佈和引用情況。

通常Java Heap的分析方式則是抓取Java Hprof,然後使用MAT等工具進行分析。

* 抓取Hprof的手法,如:

第一種方式:使用am 命令

   adb shell am dumpheap {Process} file

   如: 

 adbshell chmod 777 /data/anr

 adbshell am dumpheap com.android.phone /data/anr/phone.hprof

 adbpull /data/anr/phone.hprof

 第二種方式:使用DDMS 命令

 在DDMS中選擇對應的process,然後在Devices按鈕欄中選擇Dump Hprof file,保存即可

 第三種方式:通過代碼的方式

   在android.os.Debug這個class 中有定義相關的抓取hprof 的method。

 如: public static void dumpHprofData(String fileName) throwsIOException;

 這樣即可在代碼中直接將這個process的hprof 保存到相對應的文件中,注意這個只能抓取當時的process。

 如果想抓其他的process的hprof,那麼就必須通過AMS幫忙了。

 可以先獲取IActivityManager接口,然後調用它的dumpheap方法。具體的代碼,大家可以參考

 frameworks/base/cmds/am/src/com/android/commands/am/am.java中的調用代碼

第四種方式:發送SIGUSER1 

   在部分機器中,如果具有root權限,可以直接發送SIG 10來抓取,此時對應的Hprof保存在/data/misc下面,文件名如:

 heap-dump-tm1357153307-pid1882.hprof

* 快速分析

首先, DVM的Hprof 和標準的Java Hprof 有一些差別,需要使用hprof-conv進行一次轉換,將DVM格式的hprof 轉換成標準的java 命令的hprof

   hprof-conv in.hprof out.hprof

其次,使用如MAT Tool,打開轉換後的hprof文件,通常我們會

 analysis java thread information

 analysis java var value

 analysis Object reference

 analysis GC path

具體如何使用MAT分析可以參考MAT 的官方網站。

 3. Native 運行環境分析

Native 運行環境分析,我們通常會採用Core dump分析手法。 Core dump紀錄了當時進程的各類關鍵資訊,比如變量參數,線程stack, heap, register等。通常可以認爲是這個Process當時最爲完整的資訊了。但Core dump往往比較大,有時甚至會超過1G,屬於比較重量型的分析手法了。

* 如何抓取Core Dump。

  目前MTK的機器會將Core Dump轉換成AEE DB。否則對應的Core dump文件即存放在/data/core目錄下

  手工抓取時,可以:

  adb shell aee -d coreon

  adb shell kill -31 PID

  此時core dump就可能存放在兩個目錄下:/data/core,以及/sdcard/mtklog/aee_exp下面新的DB 文件。

* 如何分析Core Dump。

  因爲通常已經將Core Dump轉換成了AEE DB。所以首先將AEE DB解開,即可以看到PROCESS_COREDUMP的文件,有的時候此文件很大,比如超過1G。

  而分析Core Dump的Tools 很多,比如traces32, GDB等,這裏就不詳加說明,可以參考網絡上的相關文檔。

5.3       Kernel 運行環境分析

從82平臺上多了ramdump功能,可以發生KE後將82/92的物理內存壓縮保存到EMMC的內置卡(默認保存到EMMC內置卡上)(92可以選擇外置t卡)上,拿到該文件後就可以轉換爲kernel space,查看kernel各種變量,比查看kernel log更加方便快捷。

只有在eng版本下支持該功能,並且是EMMC的,存在內置T卡才行,

在projectConfig.mk裏的MTK_SHARED_SDCARD必須爲no即MTK_SHARED_SDCARD=no

連上adb後:

adb shell

#echo Y> /sys/module/mrdump/parameters/enable

#echo emmc> /sys/module/mrdump/parameters/device  (注意82只能在EMMC內置t卡上,不能下這條命令,92可以下這條命令修改到sdcard:#echo sdcard > /sys/module/mrdump/parameters/device)

這樣就開啓了ramdump功能,注意重啓後無效,必須重新設置才行

之後重新開機,此時會在

內置T卡:/storage/sdcard0/

或外置T卡:/storage/sdcard1/

看到CEDump.kdmp文件,結合kernel/out/vmlinux或out/target/product/$proj/obj/KERNEL_OBJ/vmlinux一起提供給Mediatek即可做進一步kernel異常重啓的分析。

6.     死機問題場景

當你遇到死機問題時,你可能面臨的是下面三種情況。

* 有死機現場

  資訊最爲充足,你可以快速的利用死機現場來分析。

* 已經重啓過的手機

  死機現場已經不復存在,但手機還沒有刷機,可以從手機中抓取已經存在的資訊來分析。

* 僅僅一些LOG或者其他的資訊

  需要從這些LOG或者資訊中猜測當時手機的狀態,以及可能死機的原因。

 從這三種情況,不難得知,有死機現場的情況下是最容易分析的。而如果僅僅只有一些LOG的話,就需要工程師具有非常豐富的經驗,從僅有的LOG中,提取有價值的資訊,來猜測出當時死機的原因。

7.     死機問題現場分析

7.1       死機現場分析手法

死機分析如同醫生給病人診斷病情,所有的手法不在乎分爲兩種。

* 高科技的診斷設備,分析病人的病情。死機分析就依靠各種技術方法去診斷當時手機的運行的真實狀態。

* 通過病人的各種活動,分析病人的潛在病因。就依靠各種對手機的操作,以及命令,讓手機跑相應的流程,從而進一步分析。

7.2       基本分析流程

 

 下面我們將針對每一個流程進行具體的說明。

7.3       Test Phone Usage

* 通過做一些基本的測試,可大體上確認可能引發死機的模塊,爲後續Debug確定好方向。

* 通常只能正向推理,可以做什麼 =》推斷什麼模塊正常;逆向推理可能因爲各種原因而失常。

 *Touch Panel

  - 屏幕是否有響應(一般情況下沒響應)。

  - 如果有響應,可能機器已經活過來了,或者當時把ANR認爲了hang 機;需要進一步確認情況。

  - 確認按鍵的情況,通常都設定振動反饋,如果有,那麼就認爲當時按鍵事件可以傳遞到SystemServer,此時可能System Server 邏輯異常。

 *Power Key/ Volumn Up/Down Key

  - 是否可以亮、滅屏

  - 可點亮關閉屏幕,說明KPD ->input manager->PowerManagerService->Power->LCDdriver正常;通常可以懷疑TPD,以及SurfaceFlinger。

 * 是否可以顯示音量調整情況

  - 可顯示音量調整情況,進一步說明SurfaceFlinger也正常,進一步懷疑TPD,或者直接的APP無響應的情況。

 *SystemUI & Status Bar

  - Status Bar 是否可以拉下,以便防止只是活動區卡住的情況,可下拉,說明只是APP卡住,或者lockscreen無法解鎖的情況

*LockScreen

  - 測試LockScreen是否可以解鎖,

* Home Key/ Back Key/Menu Key

  - 確認當時是否只是APP hang住的情況,避免將ANR誤判爲死機

* 插入USB觀察充電情況

  - 可確認Surfaceflinger, System Server的運行情況

7.4       USB/ADB Debug Hang

7.4.1 USB/ADB Debug 準備

* 插入USB,確認ADB是否可以使用

 - 首先查看windows的設備管理器裏面是否出現對應的設備

 - 在命令行中輸入adb devices,看是否可以打印設備信息,在輸入之前您最好先輸入adb kill-server 保證pc上的adb client沒有卡住

 - 請確保您使用的PC上已經安裝ADB,USB端口本身正常

7.4.2 USB/ADB 連接分析

 *Case1: adb 能正常連接,adb shell #

- adb 目前可以正常接入,可以進行USB/ADB Debug

 *Case2: windows 設備管理器有反應,adb shell提示device not found。

- 確認adb驅動是否安裝好,USB的uid 和 vid 是否和driver匹配。

- 可能機器的adbd已經無法對接,嘗試adbkill-server來確認

 *Case3:  windows 設備管理器有反應,adb shell提示offline。

- 機器的adbd拒絕連接,或者adbd無法拉起。

- PC adb 版本過低

- 很可能adbd已經卡住, adbdprocess status爲 ‘D’

7.4.3 機器狀態基本檢測

* ps or ps-t or ps -t -p查看進程基本狀態

 -t  以線程爲單位打印

 -p  附加打印線程優先級信息

 ** 追查如system server, surfaceflinger, service manager, media server(ss, sf, sm、ms),zygote,等關鍵進程的狀態,進行初步確認。正常情況下,都應處於’S’,異常情況有如’D’, ‘T’, ‘Z’ , ‘R’等

** 大體追查ss, sf, sm, ms, zygote等的memory情況,是否有明顯的溢出情況

** 大體查看當時的ss pid, sf pid,如果機器上層沒有重啓過,通常sf pid < 200, ss pid < 600,如果pid比較大就說明上層重啓過。

** 是否還存在特別進程,如ipod,表示在ipo關機中,如aee_core_forworder,表示在抓core dump,aee_dumpstate表示aee 在抓取db 信息等。 

** 追查debuggerd的process 數量,通常正常時,只有一個debuggerd process,pid < 200,如果有達到4個debuggerd,這個時候將無法進行rtt之類的操作

* df

- 審查storage的使用情況,查看SD 卡和 data 分區使用情況,特別是如SD卡已滿,或者data 分區寫滿等。

 * catproc/meminfo, procrank

- 審查當前的memory使用情況,追查各個進程的memory情況

*getprop 

- 審查當前system properties情況

 * top-t -m 5 -n 2

- 摸一摸手機,感覺有點熱,或者發燙的話,說明通常是CPU利用率比較高

- 大體上審查當前CPU的利用情況,不求精湛

總之,機器狀態基本檢測,目標就是通過簡單幾個命令直接偵測當前手機最爲可能的異常情況。包括關鍵進程基本狀態, CPU利用率,memory 狀況,storage 狀況等。做出基本的預先分析,從而爲下一步的debug打好基礎。

7.5       UART Debug

當usb/adb無法確認問題時或者已經無法連接時,我們需要利用UART/KDB來進一步釐清問題。

確認UART以及 UART Console已經開啓。

ENG 版本默認開啓,User版本默認關閉。通常在User版本上如果需要抓取UART日誌的話需要用散件工具單燒ENG版本的LK分區重啓就可以抓取UART日誌了。

目前我司一般的UART端口都不支持輸入,所以只能通過輸出的UART輸出的log來分析問題。

7.6       確認死機的模塊

我們又回到了最開始的可能會導致死機的模塊,下面我們將針對每一個模塊做詳細的說明。

Input Driver-Input System

* 確認Input Driver-Input System通路是否正常,即inputdriver是否可以傳上正常的輸入

* 最常見的檢測方式是 adb shell getevent

如直接輸入adb shell getevent可以看到:

D:\log>adbshell getevent

add device1: /dev/input/event0

 name:     "mtk-kpd"

could notget driver version for /dev/input/mouse0, Not atypewriter

add device2: /dev/input/event3

 name:     "mtk-tpd"

add device3: /dev/input/event2

 name:     "hwmdata"

add device4: /dev/input/event1

 name:     "ACCDET"

could notget driver version for /dev/input/mice, Not atypewriter

 對應的操作命令是:

Usage:getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q][-c count] [-r] [device]

   -t: show time stamps

   -n: don't print newlines

   -s: print switch states for given bits

   -S: print all switch states

   -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)

   -d: show HID descriptor, if available

   -p: show possible events (errs, dev, name, pos. events)

   -i: show all device info and possible events

   -l: label event types and names in plain text

   -q: quiet (clear verbosity mask)

   -c: print given number of events then exit

   -r: print rate events are received

 通常我們會一項一項的確認native層是否可以收到Kernel傳遞來的input event事件。

比如我們追查KPD是否有效果,按power key可以看到相關的行爲。

D:\log >adbshell getevent -t -l /dev/input/event0

[1388629316.433356]EV_KEY       KEY_POWER           DOWN

[1388629316.433356]EV_SYN      SYN_REPORT           00000000

[1388629316.527596]EV_KEY      KEY_POWER            UP

[1388629316.527596]EV_SYN      SYN_REPORT           00000000

[1388629317.824871]EV_KEY      KEY_POWER           DOWN

[1388629317.824871]EV_SYN      SYN_REPORT           00000000

[1388629317.996095]EV_KEY      KEY_POWER            UP

[1388629317.996095]EV_SYN      SYN_REPORT           00000000

[1388629319.495346]EV_KEY      KEY_POWER           DOWN

[1388629319.495346]EV_SYN      SYN_REPORT           00000000

[1388629319.530963]EV_KEY      KEY_POWER            UP

[1388629319.530963]EV_SYN      SYN_REPORT           00000000

 當然如果屏幕是點亮時,肯定就要快速追查tpd以及模擬按鍵是否正常

D:\log >adbshell getevent -t -l /dev/input/event5

[1388629590.432516]EV_ABS       ABS_MT_TOUCH_MAJOR  00000012

[1388629590.432516]EV_ABS       ABS_MT_TRACKING_ID  00000000

[1388629590.432516]EV_KEY      BTN_TOUCH           DOWN

[1388629590.432516]EV_ABS       ABS_MT_POSITION_X   000000d4

[1388629590.432516]EV_ABS       ABS_MT_POSITION_Y   00000280

[1388629590.432516]EV_SYN      SYN_MT_REPORT        00000000

[1388629590.432516]EV_SYN      SYN_REPORT           00000000

[1388629590.496797]EV_ABS       ABS_MT_TOUCH_MAJOR  00000010

[1388629590.496797]EV_ABS       ABS_MT_TRACKING_ID  00000000

[1388629590.496797]EV_ABS       ABS_MT_POSITION_X   000000d4

[1388629590.496797]EV_ABS       ABS_MT_POSITION_Y   0000027d

[1388629590.496797]EV_SYN      SYN_MT_REPORT        00000000

[1388629590.496797]EV_SYN      SYN_REPORT           00000000

[1388629590.506985]EV_ABS       ABS_MT_TOUCH_MAJOR  00000010

[1388629590.506985]EV_ABS       ABS_MT_TRACKING_ID  00000000

[1388629590.506985]EV_ABS       ABS_MT_POSITION_X   000000d3

[1388629590.506985]EV_ABS       ABS_MT_POSITION_Y   0000027a

[1388629590.506985]EV_SYN      SYN_MT_REPORT        00000000

[1388629590.506985]EV_SYN      SYN_REPORT           00000000

[1388629590.517713]EV_KEY      BTN_TOUCH            UP

[1388629590.517713] EV_SYN      SYN_MT_REPORT        00000000

[1388629590.517713]EV_SYN      SYN_REPORT           00000000

 如果發現無法收到此類資訊,那麼就可以確認對應的devices可能有故障,需要請對應的driver& vendor工程師來分析。

system-server logic

此分析的關鍵在於分析 system-server是否還在正常的運轉,這是非常重要的,據統計,40%的usb可以debug 的hang 機問題,都可以通過對system-server邏輯的審查找出原因。

 Systemserver 是整個android上層的中樞,容納了最爲重要的service。

 對System server的分析主要是通過java native的backtrace來追查Systemserver的關鍵thread 有沒有被lock/dead lock,有沒有進入dead loop,狀態是否正常。

 從死機機的角度來看system server關鍵的thread 如:

Serverthread:

System-server的main looper建立在serverthread上,所有service如果不單獨創立thread-looper那麼都將運行在這個Server thread上,其關鍵性不言而喻,用watchdog來監測該thread。

ActivityManager:

處理所有的Activity狀態切換,broadcast,以及ANR 監測等等,非常重要。

WindowManager:

處理各種window疊加與切換,Input相關處理。

WindowManagerPolicy/UI:

主要處理LockScreen相關流程,它卡住,lockscreen無法解鎖

PowerManagerService:

處理Power相關事宜,它卡住,屏幕無法熄滅,點亮

InputDispatcher/InputReader

處理Input System相關事宜,一旦他們卡住,那麼所有的Input Event都無法反饋到其他的module,機器死機就成必然。

在KK以及KK 以後的版本中Google 取消了serverthread這樣的main looper thread,直接使用system server 的第一個thread作爲main looper。 Google對system server的threads 做了進一步的整合,以減少繁雜的線程數,新增瞭如android.io,android.ui,android.fg,android.bg等threads。將大量的普通型的Handler按時效分類分散到上面的4個threads中。

所以KK及更高的版本還需要分析ndroid.io, android.ui, android.fg, android.bg等thread。

 這些thread都通過執行MQ-Looper-Handler的模式運行,所以正常的時候的java/native backtrace都是:

Java:

  at android.os.MessageQueue.nativePollOnce(NativeMethod)

  at android.os.MessageQueue.next(MessageQueue.java:138)

  at android.os.Looper.loop(Looper.java:150)

Native:

  #00  pc 0002599c /system/lib/libc.so (epoll_wait+12)

  #01  pc 000105e3 /system/lib/libutils.so (android::Looper::pollInner(int)+94)

  #02  pc 00010811 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92)

  #03  pc 0006ca5d /system/lib/libandroid_runtime.so(android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22)

 一旦不是就可能已經出現異常了。

BinderThread

Systemserver 爲外界提供服務,絕大多數都通過binder與其他process 對接。BinderThread 的數量動態調整,默認不會超過16個,如果數量達到16個,即說明當前system server可能非常繁忙,有process非常頻繁的和Process通信。

在JB以及以前版本,System-server的第一個thread,在調起serverthread後,自己加到IPCthread pool中,成爲Binder Thread的一員。 

對於Binder Thread,正常時對應的Backtrace:

  #00  pc 000247e8  /system/lib/libc.so(__ioctl+8)

  #01  pc 00038248  /system/lib/libc.so (ioctl+28)

  #02  pc 0001d3a9  /system/lib/libbinder.so(android::IPCThreadState::talkWithDriver(bool)+140)

  #03  pc 0001dae3  /system/lib/libbinder.so(android::IPCThreadState::getAndExecuteCommand()+6)

  #04  pc 0001db79  /system/lib/libbinder.so(android::IPCThreadState::joinThreadPool(bool)+48)

  #05  pc 00021a79  /system/lib/libbinder.so

  #06  pc 0000ea01  /system/lib/libutils.so(android::Thread::_threadLoop(void*)+216)

  #07  pc 0004f1c9 /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+68)

  #08  pc 0000e533  /system/lib/libutils.so

  #09  pc 0000d600  /system/lib/libc.so(__thread_entry+72)

  at dalvik.system.NativeStart.run(Native Method)

 抓取system server的java backtrace,依次check serverthread(JB),ActivityManager, WindowManager, WindowManagerPolicy,PowerManagerService以及android.io, android.bg, android.fg, android.ui的狀態,如狀態異常,則依次推導。

當發現java backtrace最後調用到異常nativemethod時,抓取其native backtace,通過native backtrace 進一步追查.

如果在native backtrace中,發現已經調入binderdriver,那就是通過binder進行IPC call,這個時候就要知道binder的對端process,然後查閱它的binder thread進程進一步分析問題。

 Case1: Abnormal Java Backtrace “Deadlock”

圖片deadlock-java-backtrace.png

 

 Case2: Abnormal Java Backtrace “Lock in native thread"

圖片lock-in-native-thread.png

 

 Case3: Abnormal native Backtrace “Lock in Binder”

圖片lock-in-binder.png

 

 Case4: Abnormal native Backtrace "Lock in Binder thread"

圖片lock-in-binder-thread.png

 

 當確認前面的key thread都沒用問題,而通過getevent確認event 已經傳遞到system server。問題可能出在inputsystem中。

WindowManagerService通過InputManager提供的接口開啓一個線程驅動InputReader不斷地從/dev/input /目錄下面的設備文件讀取事件,然後通過InputDispatcher分發給連接到WindowManagerService服務的客戶端。

 Input Reader 正常的backtrace:

"InputReader" sysTid=611

#00 pc 00027754 /system/lib/libc.so(epoll_wait+12)

#01 pc 0001f345 /system/lib/libinput.so(android::EventHub::getEvents(int, android::RawEvent*, unsigned int)+1092)

#02 pc 0002aaf7 /system/lib/libinput.so(android::InputReader::loopOnce()+142)

#03 pc 00027613 /system/lib/libinput.so(android::InputReaderThread::threadLoop()+8)

#04 pc 00015318 /system/lib/libutils.so(android::Thread::_threadLoop(void*)+492)

#05 pc 0004d12b/system/lib/libandroid_runtime.so(android::AndroidRuntime::javaThreadShell(void*)+150)

#06 pc 00014948 /system/lib/libutils.so

#07 pc 0000f66c /system/lib/libc.so (__thread_entry+80)

 Input Dispatcher 正常的backtrace:

"InputDispatcher" sysTid=610

#00 pc 00027754 /system/lib/libc.so(epoll_wait+12)

#01 pc 0001c05c /system/lib/libutils.so(android::Looper::pollInner(int)+140)

#02 pc 0001c3d4 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+76)

#03 pc 00026317 /system/lib/libinput.so(android::InputDispatcher::dispatchOnce()+94)

#04 pc 0001f5bd /system/lib/libinput.so(android::InputDispatcherThread::threadLoop()+8)

#05 pc 00015318 /system/lib/libutils.so(android::Thread::_threadLoop(void*)+492)

#06 pc 0004d12b/system/lib/libandroid_runtime.so(android::AndroidRuntime::javaThreadShell(void*)+150)

#07 pc 00014948 /system/lib/libutils.so

#08 pc 0000f66c /system/lib/libc.so(__thread_entry+80)

 Backtrace通常都可以精確的定位問題點,比如卡在了哪一行。

那有沒有可能您抓backtrace時,恰好運行到,造成烏龍的情況呢?這個通常需要具體情況具體分析

--- NativeBacktrace 處於R狀態

--- JavaBacktrace 處於 Suspend狀態, Running狀態

---Backtrace 處於明確的非block狀態

--- DoubleBacktrace 確認是否CPU有運轉

隨着android版本的推進,system-server越來越顯得龐大,爲此Google對system-server做了分拆動作.

After 4.0 SurfaceFlinger removed from system-server and created by init, single process SurfaceFlinger。

除SurfaceFlinger外,對system-server影響最大的是MediaServer。

注意對於surfaceflinger, mediaserver等非DVM Process,切忌不要對他們send signalSIGQUIT(3),將導致對應的process直接退出

Display logic

DisplayControl Flow

圖片: display-control-flow.png

 

 *Surface Manager(Surfaceflinger)

**Surfaceflinger 是用戶空間中Framework下libraries中負責顯示相關的一個模塊 

** 當系統同時執行多個應用程序時,Surfaceflinger負責管理顯示,主要包括顯示的疊加和顯示的渲染 

** 其中顯示的疊加,MTK架構按照一定的原則和算法,主要用到GPU和 OVL 模塊的overlay 功能來做2D/3D 繪圖的顯示合成

 * HWC

** 基於DDP OVL硬件做HW Overlay功能

 * GPU(Graphic Processing Unit )

**aspecialized electronic circuit designed to accelerate the image processing, frame buffer rendering for output to a display。

 *FrameBuffer 

** 基於Linux Frame buffer模型的MTKFramebuffer實作,主要來管理frame buffer。

 *DDP(DisplayData Path)

** MTKDisplay Hardware Controller,包括OVL, DMA, Color Processor,BLS,  DSI/DBI/DPIController

 DisplayData Flow

圖片: display-data-flow.jpg

 

 * Display大致的流程說明

** APP(包括WMS)會把數據透過Surface送到SF(surfaceflinger)

** SF 按照一定規則,通過GPU/HWC把多個Surface合成,並設定到DDP OVL 的對應layer

*** MTK OVL一般有4 layer(可能不同平臺會有差異,目前基本都是4 layer),每個layer都可以設定一個對應的圖層,然後OVL把這寫圖層合成後送給DDP的下一級Module

*** 某些情況下(比如總的圖層超過4個,OVL無法處理等各種case),會使用GPU 去做2D/3D 的圖層合成到frame buffer

** SF/HWC 最後把GPU合成圖層以及需要OVL合成的圖層,設定到OVL的HW Register,並trigger HW Engine

** MTK DDP 就會把合成的數據像管道一樣流向LCM module,最後Panel顯示相關的畫面

  對Display的快速分析,我們主要是兩個手段,第一個確認FrameBuffer數據是否和理想數據一致,第二個確認SurfaceFlinger狀態是否正確。

* 確認FrameBuffer數據和理想數據一致,那麼說明android上層的處理行爲都是正常的,而問題就很可能出在LCM的driver 或者 LCM 本身問題,此時需要聯繫LCM的driver 工程師以及 LCM vendor 來確認分析,這裏不再詳細說明。

 * 確認SurfaceFlinger的狀態,用於審查SurfaceFlinger的行爲是否正常,對應的Thread是否能夠正常工作,我司已經在SurfaceFlinger裏面導入了Watchdog機制,審查SurfaceFlinger是否有卡住的情況,對應在main log裏面會打印如: 

 [SF-WD]detect SF maybe hang!!! 

這樣的LOG,並且會紀錄卡頓的時機,如果持續卡頓,毫無疑問, SurfaceFlinger已經卡住,此時就要分析對應的backtrace以及 LOG。

*SurfaceFlinger 的線程情況在不同的版本上變化比較大,最直接的方式是審查它binder thread情況,以及Event Loop的執行情況。 binderthread和 system server情況一致,不再詳細說明。 Event Loop在JB 以及,JB 以及KK上都不相同,這裏分別說明。

 在JB以前的版本,SurfaceFlinger的Event Loop使用的是普通的pthread控制,並且SurfaceFlinger的第一個Thread 在執行SurfaceFlinger 的初始化後,轉換爲了binder thread。而Event Loop的thread 是新起的 "SurfaceFlinger" thread。對應的正常backtrace是:

圖片: surfaceflinger-event-loop-beforce-jb.png

 

 在JB版本,SurfaceFlinger的Event Loop換成了Message Queue-Looper,對應的backtrace是:

圖片: surfaceflinger-event-loop-jb.png

 

 在KK版本,SurfaceFlinger的第一個thread 直接作爲了Event Loop thread,對應的backtrace是:

圖片: surfaceflinger-event-loop-kk.png

 

 然後再根據SurfaceFlinger的代碼邏輯,以及backtrace的lock 情況進行審查分析。

8.     無現場猜測分析

8.1       無場景猜測與分析

前面已經提到,無場景分成兩類

* 已經重啓過的手機

  死機現場已經不復存在,但手機還沒有刷機,可以從手機中抓取已經存在的資訊來分析。

  *僅僅一些LOG或者其他的資訊

  需要從這些LOG或者資訊中猜測,當時手機的狀態,以及可能死機的原因。

  對於前者,如同法醫解剖逝者遺體,分析可能的死亡原因。而對於後者,就相當於警察叔叔對一些曾年舊案的考證,挖掘與分析,難度可想而知。

8.2       死機資訊的完整紀錄

爲了能夠更好更快的分析死機問題,通常我們都強烈建議保存好現場,如果一些特殊環境下無法保存現場,那麼就要求測試工程師詳細的紀錄當時現場環境,包括但不限於下面的資訊:

* 發現死機的時間

--- 如果是發現時,感覺機器早已經死機,也請說明

--- 如有截圖,拍照,可以從圖像上先獲取

 * 復現手法,操作的流程,當時環境

--- 強調在正常使用到死機過程中的操作。

--- 環境狀態通常包括溫度,溼度,網絡信號狀況。

--- 復現流程的視頻

 * 復現手機情況

--- 復現的軟件版本:版本號?

--- 外部設備情況:有插入SD卡?耳機?SIM ?

--- 軟件開啓情況:  開啓藍牙? WIFI?數據服務?GPS?

 *復現的概率

--- 多少臺手機做過測試,多少臺手機可以復現。

--- 前後多少個版本可以復現,從哪個版本開始可以復現。

 其中死機的時間點至關重要,需要現場的工程師一定要比較精確的紀錄。

8.3       死機Log 分析

* 確認hang機時間,和當時是否已經死機至關重要

* 如果當時kernel已經異常,mobile log無法抓取log,那麼log的價值大打折扣。

* 反過來如果當時mobile log還在繼續,說明至少kernel整體功能正常,先分析android上層的情況。

* 從LOG中分析SystemServer, Surfaceflinger行爲是否正常,是否有Lock住。

* 查看System Server中關鍵Service 執行情況,如AMS, WMS, PowerManagerService, WindowManagerPolicy。

* 觀測AMS是比較快速的方法,因爲AMS工作時,會使用到很多其他Service的Lock,比如broadcast, start activity, start service。通常一旦system server有卡住,則AMS 也會卡住,反過來如果AMS 沒有卡住,那麼通常就意味着systemserver沒有直接卡住。

* 查看Surfaceflinger,先查sf-wd,看看是否surfaceflinger是否已經卡住,然後再追查fps情況,HWComposer等情況。

* 查看Power Key行爲來確認上下通路是否正常,一般人看到死機,通常會去按一下Power Key來確認是否死機。

* 查看Binder信息,看看Systemserver, Surfaceflinger等的IPC 情況。

按Power Key 分析

因爲死機,一般人都會習慣性的按Power key來查看是否可以恢復,而按Power Key的處理流程,涉及從Kernel => Input System => System Server => SurfaceFlinger等的整個流程,我們可以觀察這個流程來查看hang機情況。

* KPDreceives Interrupt and generate Power Key

圖片: power-key-1。png

 

* Systemserver receives Key and call set_screen_state

圖片: power-key-2。png

 

* PowerState Update:  request_suspend_state

圖片: power-key-3.png

 

* Setscreen on:  mt65xx_leds_set_cust

圖片: power-key-4.png

 

 通過審查每一個階段流程,確認可能的hang機點。注意的是不同的版本可能有所不同,可以先用正常的機器復現一次後比對。

8.4死機Log 分析, trace 輔助

* 如果有提供/data/anr下的trace,或者相關的db文件。在確認死機的時間下,check trace對應的時間點,如果時間在死機或者hang機後,則是一份非常有價值的trace。通常查“-----”or “pid”

* 藉機審查system server, surfaceflinger的狀況。

* 如果/data/anr下有標準full_traces_xx即標柱這個backtrace是 SWT 產生的寶貴backtrace,裏面一定有system server等的backtrace。

9.     死機日誌抓取

 通常情況下,依靠Log可以找到對應的異常模塊,但無法找出根本原因。需要依賴更多的信息來debug確認,所以針對這種情況,我們需要讓測試人員抓出更多的信息來分析。

9.1       當機器死機時,建議使用下面腳本抓取資訊:

@echo "Pull important informationfrom hang phone, written by Yanghui Li"

adb devices

@echo "attach sdcard/mtklog"

adb pull /sdcard/mtklog mtklog/

 @echo “attach sdcard2/mtklog”

adb pull /sdcard2/mtklog mtklog/sdcard2

 @echo "attach trace"

adb pull /data/anr mtklog/anr

@echo "attach rtt dump forsurfaceflinger"

adb pull /data/rtt_dump* mtklog/sf_dump

adb pull /data/anr/sf_rtt mtklog/sf_rtt_1

@echo "attach data aee db"

adb pull /data/aee_exp mtklog/data_aee_exp

@echo "attach data mobilelog"

adb pull /data/mobilelogmtklog/data_mobilelog

 @echo "attach NE core"

adb pull /data/core mtklog/data_core

 @echo "attach tombstones"

adb pull /data/tombstonesmtklog/tombstones

 @echo “attach phone state”

adb shell ps -t> mtklog/ps.txt

adb shell top -t -m 5 -n 3 > mtklog/top.txt

adb shell service list  > mtklog/serviceList.txt

adb shell cat /proc/meminfo >mtklog/meminfo

adb shell cat /proc/buddyinfo >mtklog/buddyinfo

adb shell procrank > mtklog/procrank.txt

adb shell cat proc/sched_debug >mtklog/sched_debug.txt

adb shell cat proc/interrupts >mtklog/interrupts.txt

adb shell dumpstate > mtklog/dumpstate.txt

@echo "finish."

pause

9.2       當機器重啓後,可以使用下面腳本抓取:

adb devices

@echo"抓出sdcard/mtklog"

adb pull/sdcard/mtklog mtklog/

 @echo"抓出trace"

adb pull/data/anr mtklog/anr

 @echo"抓出data aee db"

adb pull/data/aee_exp mtklog/data_aee_exp

 @echo"抓出data mobilelog"

adb pull/data/mobilelog mtklog/data_mobilelog

 @echo"抓出NE core"

adb pull/data/core mtklog/data_core

 @echo"抓出tombstones"

adb pull/data/tombstones mtklog/tombstones

 @echo"抓sf rtt"

adb pull/data/rtt_dump* mtklog/sf_rtt

adb pull/data/anr/sf_rtt mtklog/sf_rtt_1

 @echo"完成"

pause

應當說針對不同的場景,死機和重啓意義不一樣。

對於普通用戶來說,死機的危害性和重要性遠大於重啓。死機意味着機器在很長一段時間內機器都運行不正常,不能使用。危害性僅次於不能開機。重啓很多時候用戶都無法感知到,除非當時正在操作手機,並且通常很快就可以恢復。所以在USER版本中,我們要儘可能的把死機轉換成重啓。

對於開發者來說,重要的是解決問題,通常把死機轉換成重啓,爲了規避一些未知因素,通常抓取的資訊比較少,難以直接分析問題。而如果有死機的現場,分析起來就相對容易得多。

所以針對ENG版本,我們建議不要把死機轉換成重啓。針對USER版本,儘可能的把死機轉換成重啓。

10.2   死機如何轉換成重啓

死機轉換成重啓的通用手段就是Watchdog機制,通過watchdog監測系統執行情況,一旦發生watchdog timeout,則做相應的異常處理。通常對於嚴重的情況,就是重啓系統。

 在android中有兩個最爲重要的Watchdog機制,一個是System Server內部的Watchdog,用於監測System Server重要Thread 是否正常,關鍵Lock是否可以快速獲取。一旦出現故障,則快速重啓android上層。另外一個就是整個系統的Watchdog,這個依賴於不同平臺廠商的實現,對於MTK平臺來說,大體的做法是每一個cpu core對應一個Watchdog Thread [wdtk-X],週期性(20s)的去寫RGUregister,而RGUregister的timeout 時間是30s,即如果出現一個core的watchdog thread沒有按時踢狗,那麼就會觸發一個timeout的FIQ,產生一個KE引發系統完整重啓。

 MTK 在KK以後的平臺,又做了hangmonitor機制, system server的watchdog thread週期性的踢kernel中的一個計時器,並設定下一次踢狗的時間,如果在設定的時間內沒有踢狗,即意味着system server的watchdog 本身可能卡住,那麼hang monitor機制就會自己觸發一個HWT,引發系統完整重啓。

當然並非所有的死機問題都能轉換成重啓。

10.3  死機VS重啓

HWHang                          [maybe]

IRQ Disable & run longtime       [After ICS Reboot, GB Hang]

SoftIRQ run longtime            [Reboot]

Preempt Disable longtime         [Reboot]

RT Thread busy[RT <99]           [Hang or Hanglong time then reboot]

Kernel ModuleHang               [maybe]

---- Not block watchdog thread reboot.

Native ModuleHang               [maybe]

---- Not block watchdog thread reboot.

SurfaceFlingerHang              [GB reboot, ICS/JB Hang, KK Hang long time then reboot] 

Display subsystemHang            [Hang]

LCMHang                         [Hang]

Input DriverFail                [Hang]

Input SystemHang                [GB, ICS Hang and JB, KK Reboot]

WindowManagerPolicyHang          [Maybe]

---- Need check the serverthread state

System serverdeadlock           [Reboot]

System server logicabnormal      [Maybe]

Surfaceflinger logic abnormal    [Maybe]

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