天天看點

Android的當機、重新開機問題分析方法 1.     當機現象 2.      當機分析資料 3.      幾種典型的異常情況 4.     當機運作環境分析 5.     程序運作環境分析 6.     當機問題場景 7.     當機問題現場分析 8.     無現場猜測分析 9.     當機日志抓取

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 shellgetevent

這個指令下下去以後會在螢幕上輸出目前裝置的節點,可從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 shellchmod 0777 data/anr

adb shellkill -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)",  

 "S(sleeping)",  

 "D(disk sleep)", 

 "T(stopped)",  

 "t(tracing stop)", 

 "Z(zombie)",  

 "X(dead)",  

 "x(dead)",  

 "K(wakekill)",  

 "W(waking)",  

通常一般的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]

轉載自:http://www.voidcn.com/blog/jinlu7611/article/p-5005930.html