public static Watchdog getInstance() {
if (sWatchdog == null) {
sWatchdog = new Watchdog();
}
return sWatchdog;
}
这里只是生成一个Watchdog对象。我们再看构造函数;只是简单的创建一个Handler对象,下面我们一起来看一上这个handler的实现:
final class HeartbeatHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MONITOR: {
// See if we should force a reboot.
int rebootInterval = mReqRebootInterval >= 0
? mReqRebootInterval : REBOOT_DEFAULT_INTERVAL;
if (mRebootInterval != rebootInterval) {
mRebootInterval = rebootInterval;
// We have been running long enough that a reboot can
// be considered...
checkReboot(false);
}
final int size = mMonitors.size();
for (int i = 0 ; i < size ; i++) {
mCurrentMonitor = mMonitors.get(i);
mCurrentMonitor.monitor();
}
synchronized (Watchdog.this) {
mCompleted = true;
mCurrentMonitor = null;
}
} break;
}
}
}
这里主要对MONITOR消息处理,主要是Check没有监视对象。
其实,在SystemServer里面还初始化了Watchdog另外一个方法:
Watchdog.getInstance().init(context, battery, power, alarm, ActivityManagerService.self());
我们再来看一下init方法:
mResolver = context.getContentResolver();
mBattery = battery;
mPower = power;
mAlarm = alarm;
mActivity = activity;
context.registerReceiver(new RebootReceiver(),
new IntentFilter(REBOOT_ACTION));
mRebootIntent = PendingIntent.getBroadcast(context,
0, new Intent(REBOOT_ACTION), 0);
context.registerReceiver(new RebootRequestReceiver(),
new IntentFilter(Intent.ACTION_REBOOT),
android.Manifest.permission.REBOOT, null);
mBootTime = System.currentTimeMillis();
这里主要是注册两个重启广播:第一个是没有带参数,第二个是带参数,同时还带权限检测。
我们再来看一下WatchDog线程的启动,主要是在SystemServer里面启动: Watchdog.getInstance().start()
接着再来看一下WatchDog的run方法,这个方法有种长,不过功能很简单。
public void run() {
boolean waitedHalf = false;
while (true) {
mCompleted = false;
mHandler.sendEmptyMessage(MONITOR);
synchronized (this) {
long timeout = TIME_TO_WAIT;
// NOTE: We use uptimeMillis() here because we do not want to increment the time we
// wait while asleep. If the device is asleep then the thing that we are waiting
// to timeout on is asleep as well and won't have a chance to run, causing a false
// positive on when to kill things.
long start = SystemClock.uptimeMillis();
while (timeout > 0 && !mForceKillSystem) {
try {
wait(timeout); // notifyAll() is called when mForceKillSystem is set
} catch (InterruptedException e) {
Log.wtf(TAG, e);
}
timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
}
if (mCompleted && !mForceKillSystem) {
// The monitors have returned.
waitedHalf = false;
continue;
}
if (!waitedHalf) {
// We've waited half the deadlock-detection interval. Pull a stack
// trace and wait another half.
ArrayList pids = new ArrayList();
/// M: WDT debug enhancement:
/// it's better to dump all running processes backtraces @{
// pids.add(Process.myPid());
mActivity.getRunningProcessPids(pids);
/// @}
pids.add(Process.myPid());
ActivityManagerService.dumpStackTraces(true, pids, null, null,
NATIVE_STACKS_OF_INTEREST);
waitedHalf = true;
continue;
}
}
// If we got here, that means that the system is most likely hung.
// First collect stack traces from all threads of the system process.
// Then kill this process so that the system will restart.
final String name = (mCurrentMonitor != null) ?
mCurrentMonitor.getClass().getName() : "null";
EventLog.writeEvent(EventLogTags.WATCHDOG, name);
ArrayList pids = new ArrayList();
/// M: WDT debug enhancement
/// it's better to dump all running processes backtraces
/// and integrate with AEE @{
/*
pids.add(Process.myPid());
if (mPhonePid > 0) pids.add(mPhonePid);
// Pass !waitedHalf so that just in case we somehow wind up here without having
// dumped the halfway stacks, we properly re-initialize the trace file.
final File stack = ActivityManagerService.dumpStackTraces(
!waitedHalf, pids, null, null, NATIVE_STACKS_OF_INTEREST);
*/
mActivity.getRunningProcessPids(pids);
final File stack = dumpAllBackTraces(pids);
/// @}
// Give some extra time to make sure the stack traces get written.
// The system's been hanging for a minute, another second or two won't hurt much.
SystemClock.sleep(2000);
// Pull our own kernel thread stacks as well if we're configured for that
if (RECORD_KERNEL_THREADS) {
dumpKernelStackTraces();
}
/// M: WDT debug enhancement
/// need to wait the AEE dumps all info, then kill system server @{
/*
// Try to add the error to the dropbox, but assuming that the ActivityManager
// itself may be deadlocked. (which has happened, causing this statement to
// deadlock and the watchdog as a whole to be ineffective)
Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
public void run() {
mActivity.addErrorToDropBox(
"watchdog", null, "system_server", null, null,
name, null, stack, null);
}
};
dropboxThread.start();
try {
dropboxThread.join(2000); // wait up to 2 seconds for it to return.
} catch (InterruptedException ignored) {}
*/
Slog.v(TAG, "** save all info before killnig system server **");
mActivity.addErrorToDropBox("watchdog", null, "system_server", null, null, name, null, null, null);
SystemClock.sleep(25000);
/// @}
// Only kill the process if the debugger is not attached.
if (!Debug.isDebuggerConnected()) {
Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
Process.killProcess(Process.myPid());
System.exit(10);
} else {
Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
}
waitedHalf = false;
}
}
然后第二个while里面:进入到wait状态(等待30s)直到超时再去检测是否是"锁住状态",如果是没有锁住,被监测的线程没有被锁住,则continue 退出这次检测。
如果是被锁住了,获取当前的线程,调用 AMS 的dumpStackTraces方法打印信息。继承等待30s,如果还是被锁住,则打印当前系统的信息:
mActivity.getRunningProcessPids(pids);
final File stack = dumpAllBackTraces(pids);
再重启SystemServer进程: Process.killProcess(Process.myPid());