Android Watchdog机制原理分析

本文基于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机制展开分析:、

  1. Watchdog、MonitorChecker 、Handlerchecker初始化。
  2. Watchdog 机制原理分析。
  3. 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 threadmain threadui threadi/o threaddisplay 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还提供了两个方法addMonitoraddThread供外部添加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就分别添加了monitorhandler

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;
            
  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值