Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Adnroid Watchdog實現詳解

Adnroid Watchdog實現詳解

編輯:關於Android編程

本文基於Android4.4,

 

最近查了下watchdog打印錯誤log的問題。頭都大。。。也查看了下android framework 下watchdog的實現代碼,做個記錄以備後邊溫習,以及新入行後輩們能夠快速上手

 

以PowerManagerservice為例做簡單流程分析

 

Watchdog功能:

1. 監視reboot廣播

2. 監視加到check list 的service是否死鎖

 

功能介紹:

功能1非常簡單,就是注冊一個broadcastreceiver,收到關機的Action就去走關機或reboot流程

主要說下功能2

PowerManagerService.java:

先說一下構造函數:

private Watchdog() {

super("watchdog");

// Initialize handler checkers for each common thread we want tocheck. Note

// that we are not currently checking the background thread, since itcan

// potentially hold longer running operations with no guarantees aboutthe timeliness

// of operations there.

 

// The shared foreground thread is the main checker. It is where we

// will also dispatch monitor checks and do other work.

mMonitorChecker = newHandlerChecker(FgThread.getHandler(),

"foreground thread",DEFAULT_TIMEOUT);

mHandlerCheckers.add(mMonitorChecker);

// Add checker for main thread. We only do a quick check since there

// can be UI running on the thread.

mHandlerCheckers.add(new HandlerChecker(newHandler(Looper.getMainLooper()),

"main thread",DEFAULT_TIMEOUT));

// Add checker for shared UI thread.

mHandlerCheckers.add(newHandlerChecker(UiThread.getHandler(),

"ui thread", DEFAULT_TIMEOUT));

// And also check IO thread.

mHandlerCheckers.add(newHandlerChecker(IoThread.getHandler(),

"i/o thread",DEFAULT_TIMEOUT));

}

紅色部分很重要,添加UIThread,FgThread,IoThread,還有當前new Watchdog時候的主線程,其實就是System_server主線程

 

接下來說下init:

public void init(Context context, LightsService ls,

ActivityManagerService am, BatteryService bs, IBatteryStats bss,

IAppOpsService appOps, DisplayManagerService dm) {

。。。。。。

mHandlerThread = new HandlerThread(TAG);

mHandlerThread.start();

mHandler = new PowerManagerHandler(mHandlerThread.getLooper());

 

Watchdog.getInstance().addMonitor(this); //添加本對象到monitor列表裡

Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName());

。。。。。。

}

public void addMonitor(Monitor monitor) {

synchronized (this) {

if (isAlive()) {

throw newRuntimeException("Monitors can't be added once the Watchdog isrunning");

}

mMonitorChecker.addMonitor(monitor);//

}

}

 

 

Watchdog構造函數裡

mMonitorChecker = newHandlerChecker(FgThread.getHandler(),

"foreground thread",DEFAULT_TIMEOUT);

 

public void addMonitor(Monitor monitor){

//mMonitors是一個數組list ArrayList mMonitors = newArrayList();

//添加powermanagerservice對象到此list

mMonitors.add(monitor);

}

 

接著說下Watchdog.getInstance().addThread(mHandler,mHandlerThread.getName());

 

public void addThread(Handler thread,String name) {

addThread(thread, name, DEFAULT_TIMEOUT);

}

 

public void addThread(Handler thread,String name, long timeoutMillis) {

synchronized (this) {

if (isAlive()) {

throw newRuntimeException("Threads can't be added once the Watchdog isrunning");

}

 

//把PowerManagerHandler 對象添加到mHandlerCheckers列表

mHandlerCheckers.add(newHandlerChecker(thread, name, timeoutMillis));

}

}

 

准備工作到此已經做完,接下來就是watchdog不停監視每個service是否死鎖

代碼主要在Watchdog.java

 

System_server會啟動watchdog會跑到run函數:

WatchDog運行在一個單獨的線程中,它的線程執行方法run()的代碼如下:

public void run() {

booleanwaitedHalf= false;

while(true){

finalArrayListblockedCheckers;

finalStringsubject;

finalbooleanallowRestart;

synchronized(this){

longtimeout= CHECK_INTERVAL;

//給監控的線程發送消息

for (inti=0; i

HandlerChecker hc =mHandlerCheckers.get(i);

hc.scheduleCheckLocked();

}

//睡眠一段時間

longstart= SystemClock.uptimeMillis();

while(timeout> 0) {

try{

wait(timeout);

}catch(InterruptedException e) {

Log.wtf(TAG,e);

}

timeout=CHECK_INTERVAL - (SystemClock.uptimeMillis() -start);

}

//檢查是否有線程或服務出問題了

finalintwaitState =evaluateCheckerCompletionLocked();

if(waitState== COMPLETED) {

waitedHalf=false;

continue;

}elseif (waitState == WAITING) {

continue;

}elseif (waitState == WAITED_HALF) {

if(!waitedHalf){

ArrayListpids= new ArrayList();

pids.add(Process.myPid());

ActivityManagerService.dumpStackTraces(true,pids,null, null,

NATIVE_STACKS_OF_INTEREST);

waitedHalf=true;

}

continue;

}

......

{

//殺死SystemServer

Process.killProcess(Process.myPid());

System.exit(10);

}

waitedHalf=false;

}

}

run()方法中有一個無限循環,每次循環中主要做三件事:

1. 調用scheduleCheckLocked()方法給所有受監控的線程發送消息。scheduleCheckLocked()方法的代碼如下

publicvoidscheduleCheckLocked() {

if(mMonitors.size() == 0 &&mHandler.getLooper().isIdling()) {

mCompleted= true;

return;

}

if(!mCompleted) {

return;

}

mCompleted= false;

mCurrentMonitor= null;

mStartTime= SystemClock.uptimeMillis();

mHandler.postAtFrontOfQueue(this);//給監視的線程發送消息

}

 

HandlerChecker對象即要監控服務,也要監控某個線程。所以上面的代碼先判斷mMonitors的size是否為0。如果為0,說明這個HandlerChecker沒有監控服務,這時如果被監控線程的消息隊列處於空閒狀態(調用isIdling()檢查),則說明線程運行良好,把mCompleted設為true後就可以返回了。否則先把mCompleted設為false,然後記錄消息開始發送的時間到變量mStartTime中,最後調用postAtFrontOfQueue()方法給被監控的線程發送一個消息。此時在Handler.java的

public voiddispatchMessage(Message msg) {

if (msg.callback != null) {

handleCallback(msg);

} else {

if (mCallback != null) {

if(mCallback.handleMessage(msg)) {

return;

}

}

handleMessage(msg);

}

}

private static void handleCallback(Message message) {

message.callback.run();

}

這個消息的處理方法是HandlerChecker類的方法run(),代碼如下:

publicvoidrun() {

finalint size = mMonitors.size();

for(int i = 0 ; i < size ; i++) {

synchronized(Watchdog.this) {

mCurrentMonitor= mMonitors.get(i);

}

mCurrentMonitor.monitor();

}

synchronized(Watchdog.this) {

mCompleted= true;

mCurrentMonitor= null;

}

}

如果消息處理方法run()能夠被執行,說明受監控的線程本身沒有問題。但是還需要檢查被監控服務的狀態。檢查是通過調用服務中實現的monitor()方法來完成的。通常monitor()方法的實現是獲取服務中的鎖,如果不能得到,線程就會被掛起,這樣mCompleted的值就不能被置成true了。

mCompleted的值為true,表明HandlerChecker對象監控的線程或服務正常。否則就可能有問題。是否真有問題還要通過等待的時間是否超過規定時間來判斷。

moninor()方法的實現通常如下:

publicvoidmonitor() {

synchronized(mLock) {

}

}

2. 給受監控的線程發送完消息後,調用wait()方法讓WatchDog線程睡眠一段時間。

3. 逐個檢查是否有線程或服務出問題了,一旦發現問題,馬上殺死進程。

前面調用了方法evaluateCheckerCompletionLocked()來檢查線程或服務是否有問題。evaluateCheckerCompletionLocked()方法的代碼如下:

privateintevaluateCheckerCompletionLocked() {

intstate = COMPLETED;

for(int i=0; i

HandlerCheckerhc =mHandlerCheckers.get(i);

state= Math.max(state,hc.getCompletionStateLocked());

}

returnstate;

}

!waitedHalf, pids, null, null,NATIVE_STACKS_OF_INTEREST);

getCompletionStateLocked()函數根據等待時間來確認返回HandlerChecker對象的狀態,代碼如下:

publicintgetCompletionStateLocked() {

if(mCompleted) {

returnCOMPLETED;

}else {

longlatency = SystemClock.uptimeMillis() -mStartTime;

if(latency < mWaitMax/2) {

returnWAITING;

}else if (latency < mWaitMax) {

returnWAITED_HALF;

}

}

returnOVERDUE;

}

到此就已經分析完畢,如果對發送消息不明白可以看我博文裡handler,looper的那篇文章。中間網上找了些博文,借鑒。如果有什麼不足之處,請指正。。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved