您的位置:首页 > 移动开发 > Android开发

Android的死机、重启问题分析方法

2018-03-28 08:59 441 查看
Android的死机、重启问题分析方法

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.txtMTKEnhance:  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.txt1.1       抓取的方式一般进程出现无响应的问题,Android系统会发送SIGQUIT(3)信号给该进程,收到这个信号会,进程会将当前的调用栈打印在trace.txt文件里。手动抓取进程的Backtrace方法如下:adb remountadb shellchmod 0777 data/anradb shellkill -3 pidadb pull/data/anr 1.2JavaBacktrace 解析下面是一小段system server的java backtrace的开始----- pid 682 at 2015-07-30 18:04:53 -----Cmd line: system_serverJNI: 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 name1#  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 CallStack1.3 几种常见的java backtrace1.3.1ActivityThread 正常状态的BacktraceMessageQueue 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 caseSynchronizedLock:等待同步锁时的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  p
20000
c 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 add3.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_mainUser 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          Proc16132 32195  3  14% R997100K  53492K  bg u0_a60  Thread-1401     com.android.mms16132 32190  1  14% R997100K  53492K  bg u0_a60  Thread-1400     com.android.mms16132 32188  2  14% R997100K  53492K  bg u0_a60  Thread-1399     com.android.mms16132 32187  0  14% R997100K  53492K  bg u0_a60  Thread-1398     com.android.mms18793 18793  4   1%R   2068K   1020K    shell   top             topUser 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          Proc16132 32195  3  16% R997100K  53492K  bg u0_a60  Thread-1401     com.android.mms16132 32188  2  16% R997100K  53492K  bg u0_a60  Thread-1399     com.android.mms16132 32190  0  16% R997100K  53492K  bg u0_a60  Thread-1400     com.android.mms16132 32187  1  16% R997100K  53492K  bg u0_a60  Thread-1398     com.android.mms18793 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 statusadb shell cat proc/meminfoadb shell cat proc/pid/mapsadb shell cat proc/pid/smaps* procrank info: all process memory statusadb shell procrankadb shell procmem pidadb shell dumpsys meminfo pid* zoneinfo:adb shell cat proc/zoneinfo* buddyinfo:adb shell cat /proc/buddyinfo

4.4       Storage Usage

查看Storage的情况,通常主要是查询data分区是否已经刷满, sdcard是否已经刷满,剩余的空间是否足够。以及是否有产生超大文件等。通常使用的命令如 dfdfFilesystem              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 等命令,如dudu -helpusage: du [-H | -L | -P] [-a | -d depth |-s] [-cgkmrx] [file …]du -LP -d 18       ./lost+found88      ./local384     ./misc48      ./nativebenchmark912     ./nativetest8       ./dontpanic13376  ./data8       ./app-private8       ./app-asec129424  ./app-lib推荐:Android Studio导致的假死机问题的解决问题描述: Android Studio启动运行时或rebuild时导致系统假死,只有鼠标能动,点击任何界面都没有反应,浏览器都没法点,都没法查,Alt+shift+delete都不好使无8       ./app136     ./property16      ./ssh116312  ./dalvik-cache8       ./resource-cache48      ./drm8       ./mediadrm8       ./security3888    ./nvram8       ./amit8       ./acdapi88      ./@btmtk32      ./sec8       ./user16      ./media16      ./agps_supl8       ./anr8       ./gps_mnl8       ./nfc_socket16      ./ccci_cfg32      ./mdlog1312    ./system176     ./recovery32      ./backup274688  .

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 geteventadd device1: /dev/input/event0 name:     "mtk-kpd"could notget driver version for /dev/input/mouse0, Not atypewriteradd 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) 一旦不是就可能已经出现异常了。BinderThreadSystemserver 为外界提供服务,绝大多数都通过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_dumpadb 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.txtadb shell top -t -m 5 -n 3 > mtklog/top.txtadb shell service list  > mtklog/serviceList.txtadb shell cat /proc/meminfo >mtklog/meminfoadb shell cat /proc/buddyinfo >mtklog/buddyinfoadb shell procrank > mtklog/procrank.txtadb shell cat proc/sched_debug >mtklog/sched_debug.txtadb shell cat proc/interrupts >mtklog/interrupts.txtadb 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_rttadb 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 stateSystem serverdeadlock           [Reboot]System server logicabnormal      [Maybe]Surfaceflinger logic abnormal    [Maybe]推荐:android 动态库死机调试方法android 动态库死机调试方法 分类: Android系统框架学习 2011-12-15 17:47 1468人阅读 评论(1) 收藏 举报 这两种方法都不是我发明了,都是网上一些高手公共出来Android的死机、重启问题分析方法 1.     死机现象 1.1      死机定义 当手机长时间无法再被用户控制操作时,我们称为死机。在这里我们强调长时间,如果是短时间,归结为性能问题。 1.2      死
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 死机 重启