本文基于AOSP-8.0.0_r11源码分析,源码可以参见frameworks/base/+/android-8.0.0_r11
如我们所知,当应用超过一定时间无响应的时候,系统为了不让应用长时处于不可操作的状态,会弹出一个“无响应”(ANR)的对话框,用户可以选择强制关闭,从而关掉这个进程。
ANR机制是针对应用的,对于系统进程来说,如果长时间“无响应”,Android系统设计了WatchDog机制来管控。如果超过了“无响应”的延时,那么系统WatchDog会触发自杀机制。
当我们分析死机重启问题LOG的时候,经常会看到下面这样一句话:
*** WATCHDOG KILLING SYSTEM PROCESS:
从字面意思上看是:看门狗杀掉了系统进程。这里就提到了本文将要分析的WatchDog机制,对于WatchDog机制来说,主要通过添加两种类型的Checker,然后每隔30s去检测一次是否有死锁和线程池堵塞的情况,如果存在,则kill掉系统。Checker主要是如下两类:
- MonitorChecker 检查系统核心服务是否被锁时间过长。
- HandlerChecker 检查系统核心线程创建的Looper管理的消息队列是否阻塞。实际上,MonitorChecker也是一种线程是FgThread的HandlerChecker。
为了方便描述,本文所指HandlerChecker不包括线程是FgThread的MonitorChecker。
接下来我们将从以下几个方面对Watchdog机制展开分析:、
- Watchdog、MonitorChecker 、Handlerchecker初始化。
- Watchdog 机制原理分析。
- Watchdog死机重启问题分析方法。
Watchdog 启动
Watchdog是一个线程,继承于Thread,在SystemServer.java里面通过getInstance获取watchdog的对象。
@SystemServer.java
final Watchdog watchdog = Watchdog.getInstance();
watchdog.init(context, mActivityManagerService);
在init
方法里面,注册了ACTION_REBOOT
的广播接收器。
public void init(Context context, ActivityManagerService activity) {
context.registerReceiver(new RebootRequestReceiver(),
new IntentFilter(Intent.ACTION_REBOOT),
android.Manifest.permission.REBOOT, null);
}
初始化HandlerChecker
在Watchdog初始化的过程中,会初始化Handlerchecker
,代码如下:
HandlerChecker(Handler handler, String name, long waitMaxMillis) {
mHandler = handler;
mName = name;
mWaitMax = waitMaxMillis;
mCompleted = true;
}
参数分别表示:
- handler: 观察的Handler.
- name: 对Handler对应的线程名字命名,主要方便后续发生异常之后,在LOG中输出对应的线程名。
- waitMaxMillis: 消息队列阻塞的最大时长,超过这个时长,就会Kill系统,默认是60s。
watchdog的构造方法里面,会初始化名字分别是foreground thread
,main thread
,ui thread
,i/o thread
,display thread
的HandlerChecker(FgThread特例),默认的DEFAULT_TIMEOUT是60s,也就是说,线程创建的Looper里面的消息队列不能阻塞超过60s。
代码如下:
private Watchdog() {
super("watchdog");
mMonitorChecker = new HandlerChecker(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(new Handler(Looper.getMainLooper()),
"main thread", DEFAULT_TIMEOUT));
// Add checker for shared UI thread.
mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(),
"ui thread", DEFAULT_TIMEOUT));
// And also check IO thread.
mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),
"i/o thread", DEFAULT_TIMEOUT));
// And the display thread.
mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
"display thread", DEFAULT_TIMEOUT));
// Initialize monitor for Binder threads.
addMonitor(new BinderThreadMonitor());
}
初始化MonitorChecker
如上代码,在初始化Watchdog的过程中,会添加BinderThreadMonitor。
*/
private static final class BinderThreadMonitor implements Watchdog.Monitor {
@Override
public void monitor() {
Binder.blockUntilThreadAvailable();
}
}
外部添加
除了WatchDog里面自己添加的固定的Checker之外,Watchdog还提供了两个方法addMonitor
和addThread
供外部添加HandlerChecker和MonitorChecker。代码如下:
public void addMonitor(Monitor monitor) {
synchronized (this) {
if (isAlive()) {
throw new RuntimeException("Monitors can't be added once the Watchdog is running");
}
mMonitorChecker.addMonitor(monitor);
}
}
public void addThread(Handler thread, long timeoutMillis) {
synchronized (this) {
if (isAlive()) {
throw new RuntimeException("Threads can't be added once the Watchdog is running");
}
final String name = thread.getLooper().getThread().getName();
mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis));
}
}
比如ActivityManagerService
就分别添加了monitor
和handler
;
public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor
{
// ...
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
watchdog 机制原理
当系统的核心服务都运行之后,SystemServer.java会调用Watchdog.getInstance().start();
从而开始执行Watchdog线程的run
方法。代码如下:
@Override
public void run() {
boolean waitedHalf = false;
while (true) {
final ArrayList<HandlerChecker> blockedCheckers;