Android WatchDog分析
AndroidWatchDog
1Android中的WatchDog
本文主要介绍androidframework层中的watchdog,它属于一种软件Watchdog实现。
WatchDog主要作用:
1).接收系统内部reboot请求,重启系统。
2).监护SystemServer进程,防止系统死锁。
2WatchDog启动
WatchDog是在SystemServer进程中被初始化和启动的。在SystemServer被Start时,各种Android服务被注册和启动,其中也包括了WatchDog的初始化和启动。代码如下:
Slog.i(TAG,"InitWatchdog");
Watchdog.getInstance().init(context,battery,power,alarm,ActivityManagerService.self());
//Watchdog本身继承Thread,是一个线程类。此为WatchDog初始化。
.在SystemServerRun函数的后半段,将检查系统是否已经准备好运行第三方代码,并通过SystemReady接口通知系统已经就绪。在ActivityManagerService的SystemReady接口的CallBack函数中实现WatchDog的启动
Watchdog.getInstance().start();
//以上代码位于/Frameworks/base/services/java/com/android/server/SystemServer.java中。
3WatchDog内部架构及主要接口介绍
WatchDog内部主要部件和接口函数为:HeartbeatHandler、RebootReceiver、RebootRequestReceiver、checkReboot、rebootSystem、Monitor、addMonitor。
HeartbeatHandler:此为WatchDog的核心,负责对各个监护对象进行监护。
RebootReceiver:负责接收由AlarManagerService发出的PendingIntent,并进行系统重启。该PendingIntent为WatchDog内部创建,"com.android.service.Watchdog.REBOOT"。
RebootRequestReceiver:负责接收系统内部发出的重启Intent消息,并进行系统重启。
checkReboot:判断是否需要重启系统。
rebootSystem:调用PowerManager的reboot接口重启系统。
Monitor:每个被监护对象必须要实现的接口,由WatchDog在运行中调用,以实现监护功能。
addMonitor:将实现了monitor接口的监护对象注册到WatchDog服务中。
4WatchDog工作流程
4.1WatchDog监护对象
要实现调用WatchDog对其进行监护,则必须实现
1)WatchDog.Monitor接口,这个接口中只有一个monitor函数。
2)将该对象注册到WatchDog服务中,在初始化中作如下处理:Watchdog.getInstance().addMonitor(this);
在Android中WatchDog运行在SystemServer进程,对其进行监护,而其中监护的服务为以下三个:
ActivityManagerService、WindowManagerService、PowerMangerService。
以ActivityManagerService为例:
/**Inthismethodwetrytoacquireourlocktomakesurethatwehavenotdeadlocked*/
publicvoidmonitor(){
synchronized(this){}
}
该接口函数其实内部并不做任何处理,只是去锁一下对象,然后返回。如果对象没有死锁,则过程会很顺利,若对象死锁,则该函数就会挂在这里。
其它两个Service对象实现的monitor接口函数与Activity类似,也同样是去获取一下锁而已。
4.2WatchDog监护流程
在WatchDog启动之后,开始跑run函数。该函数内部为一个无限循环。
publicvoidrun(){
booleanwaitedHalf=false;
while(true){
mCompleted=false;
mHandler.sendEmptyMessage(MONITOR);
...
while(timeout>0&&!mForceKillSystem){
try{
wait(timeout);
}catch(InterruptedExceptione){
}
timeout=TIME_TO_WAIT-(SystemClock.uptimeMillis()-start);
//TIME_TO_WAIT的默认时间为30s。此为第一次等待时间,WatchDog判断对象是否死锁的最长处理时间为1Min。
}
...
}
}
一开始就会发送一个MONITOR的Message,由HeartbeatHandler负责接收并处理。同时会等待30秒,等待HeartbeatHandler的处理结果。然后才会进行下一步动作。
在HeartbeatHandler中将会作如下处理:
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
caseMONITOR:{
...
finalintsize=mMonitors.size();
for(inti=0;i<size;i++){
mCurrentMonitor=mMonitors.get(i);
mCurrentMonitor.monitor();
}//依次去调用监护对象的monitor接口,实现对其的监护。具体操作内容见4.1。
synchronized(Watchdog.this){
mCompleted=true;
mCurrentMonitor=null;
}//如果监护的对象都正常,则会很快运行到这里,并对mCompleted赋值为true,表示对象正常返回。mCompleted值初始为false。
同时在run函数中:if(mCompleted&&!mForceKillSystem){
//Themonitorshavereturned.
waitedHalf=false;
continue;
}//如果所有对象在30s内能够返回,则会得到mCompleted=true;则本次监护就结束,返回继续下一轮监护。
如果在30s内,monitor对象未能返回,mCompleted值即为false,则会运行到该语句:
if(!waitedHalf){
//We'vewaitedhalfthedeadlock-detectioninterval.Pullastack
//traceandwaitanotherhalf.
ArrayList<Integer>pids=newArrayList<Integer>();
pids.add(Process.myPid());
ActivityManagerService.dumpStackTraces(true,pids,null,null);
waitedHalf=true;
continue;
}//会调用ActivityManagerService.java中的dumpStackTraces接口函数。
在该接口中,主要会对SystemServer进程的stackTrace的信息dump出来,以及检测目前运行App的CPU使用率。由SystemServer进程发送一个SIGNAL_QUIT的进程信号:
publicstaticFiledumpStackTraces(...,...){
...
Process.sendSignal(firstPids.get(i),Process.SIGNAL_QUIT);
...
//NextmeasureCPUusage.
if(processStats!=null){
processStats.init();
System.gc();//运行garbageCollector.
processStats.update();
...
//We'lltakethestackcrawlsofjustthetopappsusingCPU.
finalintN=processStats.countWorkingStats();
intnumProcs=0;
for(inti=0;i<N&&numProcs<5;i++){
ProcessStats.Statsstats=processStats.getWorkingStats(i);
if(lastPids.indexOfKey(stats.pid)>=0){
numProcs++;
try{
Process.sendSignal(firstPids.get(i),Process.SIGNAL_QUIT);
}
...
}
该动作发生在第一次等待的30s时间内,monitor对象未返回,由于在调用完ActivityManagerService.java的dumpStackTraces接口函数后,将waitedHalf赋值为true。并返回继续下一轮监护。若紧接着的下一轮监护,在30s内monitor对象依旧未及时返回,此时
if(mCompleted&&!mForceKillSystem){
...
}
if(!waitedHalf){
...
}//此时这两个语句都不会运行,则会直接运行到下面部分。这表示系统的监护对象有死锁现象发生,SystemServer进程需要kill并重启。
//Pass!waitedHalfsothatjustincasewesomehowwindupherewithouthaving
//dumpedthehalfwaystacks,weproperlyre-initializethetracefile.
finalFilestack=ActivityManagerService.dumpStackTraces(
!waitedHalf,pids,null,null);
//Givesomeextratimetomakesurethestacktracesgetwritten.
//Thesystem'sbeenhangingforaminute,anothersecondortwowon'thurtmuch.
SystemClock.sleep(2000);
...
//Onlykilltheprocessifthedebuggerisnotattached.
if(!Debug.isDebuggerConnected()){
Process.killProcess(Process.myPid());
System.exit(10);//在剩下的30s内,做一些收尾工作,如重新初始化tracefile。最后直接将SystemServer进程kill,并且退出系统。Init进程会重新启动SystemServer进程,让其回到可用状态。
更多相关文章
- 第三部分:Android 应用程序接口指南---第一节:应用程序组件---第五
- Android 无线接口层RIL
- android对html支持接口总结
- Android 匿名共享内存Java接口分析
- Android rest接口
- android 常用api 接口签名验证
- Android高手进阶教程(十七)之---Android中Intent传递对象的两种
- Android中将资源文件转为Bitmap对象
- 面向UDP的Android——PC双向通信(三):在Android客户端和PC服务器端