Android稳定性系列6 WatchDog原理

一 概述

Watchdog 中文翻译是“看门狗”,有保护,监控的意思。最早引入 Watchdog 是在单片机系统中,由于单片机的工作环境容易受到外界磁场的干扰,导致程序“跑飞”,造成整个系统无法正常工作,因此,引入了一个“看门狗”,对单片机的运行状态进行实时监测,针对运行故障做一些保护处理,譬如让系统重启。这种 Watchdog 属于硬件层面,必须有硬件电路的支持。

Linux 也引入了 Watchdog,在 Linux 内核下,当 Watchdog 启动后,便设定了一个定时器,如果在超时时间内没有对 /dev/Watchdog 进行写操作,则会导致系统重启。通过定时器实现的 Watchdog 属于软件层面。

Android 在 framework 层设计了一个软件层面的 Watchdog,用于定期检测一些重要的系统服务,当出现故障(系统核心服务和重要线程处于 Blocked 状态)时,通常会让 Android 系统重启。由于这种机制的存在,就经常会出现 system_server 进程被 Watchdog 杀掉而发生手机重启的问题。

watchdog 的源码很简单,主要有以下两个功能:

  • 监控 system_server 中几个关键的锁,原理是在 android_fg 线程中尝试加锁
  • 监控几个常用线程的执行时间,原理是在这几个线程中执行任务

二 WatchDog初始化

2.1 startBootstrapServices

SystemServer.java

private void startBootstrapServices() {
    ......
    //创建watchdog
    final Watchdog watchdog = Watchdog.getInstance();    
    watchdog.start();
    ......
    //待AMS启动后注册reboot广播
    watchdog.init(mSystemContext, mActivityManagerService);
    ......
}

system_server 进程在启动的过程中初始化 WatchDog,主要有:

  • 创建 watchdog 对象,该对象本身继承于 Thread
  • 调用 start() 开始工作
  • 注册 reboot 广播

2.2 Watchdog.getInstance

Watchdog.java

public static Watchdog getInstance() {
    if (sWatchdog == null) {
        sWatchdog = new Watchdog();//单例模式,创建实例对象
    }
    return sWatchdog;
}

2.3 创建Watchdog

Watchdog.java

public class Watchdog extends Thread {
    //所有的HandlerChecker对象组成的列表
    //This handler will be used to post message back onto the main thread
    final ArrayList<HandlerChecker> mHandlerCheckers = new ArrayList<>();
    ......

    private Watchdog() {
        super("watchdog");
        //将前台线程加入队列
        mMonitorChecker = new HandlerChecker(FgThread.getHandler(),
                "foreground thread", DEFAULT_TIMEOUT);
        mHandlerCheckers.add(mMonitorChecker);
        //将主线程加入队列
        mHandlerCheckers.add(new HandlerChecker(
        new Handler(Looper.getMainLooper()),
                "main thread", DEFAULT_TIMEOUT));
        //将ui线程加入队列
        mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(),
                "ui thread", DEFAULT_TIMEOUT));
        //将i/o线程加入队列
        mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),
                "i/o thread", DEFAULT_TIMEOUT));
        //将display线程加入队列
        mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
                "display thread", DEFAULT_TIMEOUT));
        // And the animation thread.
        mHandlerCheckers.add(new HandlerChecker(AnimationThread.getHandler(),
                "animation thread", DEFAULT_TIMEOUT));
        // And the surface animation thread.
        mHandlerCheckers.add(new HandlerChecker(
        SurfaceAnimationThread.getHandler(),
                "surface animation thread", DEFAULT_TIMEOUT));
        //Initialize monitor for Binder threads
        addMonitor(new BinderThreadMonitor());
        mOpenFdMonitor = OpenFdMonitor.create();
        // See the notes on DEFAULT_TIMEOUT.
        assert DB ||
                DEFAULT_TIMEOUT > 
                ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS;
    }
    ......
}

Watchdog 是一个单例线程,继承于 Thread,创建的线程名为 ”watchdog”。在 SystemServer 启动过程中初始化 Watchdog。Watchdog 在初始化时,会构建很多 HandlerChecker,大致可以分为两类:

  • Monitor Checker,用于检查 Monitor 对象可能发生的死锁,AMS,IMS,WMS PMS 等核心的系统服务都是 Monitor 对象
  • Looper Checker,用于检查线程的消息队列是否长时间处于工作状态。Watchdog 自身的消息队列,ui,io, Display 这些全局的消息队列都是被检查的对象。此外,一些重要的线程的消息队列,也会加入到 Looper Checker中,譬如 AMS,WMS 这些是在对应的对象初始化时加入的

两类 HandlerChecker 的侧重点不同,Monitor Checker 预警我们不能长时间持有核心系统服务的对象锁,否则会阻塞很多函数的运行;Looper Checker 预警我们不能长时间的霸占消息队列,否则其他消息将得不到处理。这两类都会导致系统卡住 (System Not Responding)。

2.3.1 Watchdog.HandlerChecker

public final class HandlerChecker implements Runnable {
        private final Handler mHandler;//Handler对象
        private final String mName;//线程描述名
        private final long mWaitMax;//最长等待时间
        //记录着监控的服务
        private final ArrayList<Monitor> mMonitors =
            new ArrayList<Monitor>();
        //添加监控服务队列
        private final ArrayList<Monitor> mMonitorQueue =
        new ArrayList<Monitor>();
        private boolean mCompleted;//开始检查时先设置成false
        private Monitor mCurrentMonitor;
        private long mStartTime;//开始准备检查的时间点
        private int mPauseCount;

        HandlerChecker(Handler handler, String name, long waitMaxMillis) {
            mHandler = handler;
            mName = name;
            mWaitMax = waitMaxMillis;
            mCompleted = true;
        }

        void addMonitorLocked(Monitor monitor) {
            mMonitorQueue.add(monitor);
        }

        public void scheduleCheckLocked() {
            if (mCompleted) {
                mMonitors.addAll(mMonitorQueue);
                mMonitorQueue.clear();
            }
            if ((mMonitors.size() == 0 &&
                mHandler.getLooper().getQueue().isPolling())
                    || (mPauseCount > 0)) {
                mCompleted = true;
                return;
            }
            if (!mCompleted) {
                // we already have a check in flight, so no need
                return;
            }
            mCompleted = false;
            mCurrentMonitor = null;
            mStartTime = SystemClock.uptimeMillis();
            mHandler.postAtFrontOfQueue(this);
        }
        ......
        @Override
        public void run() {
            final int 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;
            }
        }
       ......
    }

HandlerChecker 继承自 Runnable,里面维护着监控服务的 Monitor 对象列表,使用 addMonitor 方法将服务监听者加入列表。

2.3.2 Watchdog.addMonitor

现在我们来分析在 Watchdog 构造函数中调用的 addMonitor(new BinderThreadMonitor());

public void addMonitor(Monitor monitor) {
    synchronized (this) {
        mMonitorChecker.addMonitorLocked(monitor);
    }
}
public final class HandlerChecker implements Runnable {
        ......
        //添加监控服务队列
        private final ArrayList<Monitor> mMonitorQueue =
        new ArrayList<Monitor>();
        ......

        HandlerChecker(Handler handler, String name, long waitMaxMillis) {
            mHandler = handler;
            mName = name;
            mWaitMax = waitMaxMillis;
            mCompleted = true;
        }

        void addMonitorLocked(Monitor monitor) {
            //添加monitor到mMonitorQueue中
            mMonitorQueue.add(monitor);
        }
        ......
    }

可知最终是把 BinderThreadMonitor 对象添加到 mMonitorQueue 中了。

Watchdog.java

private static final class BinderThreadMonitor implements Watchdog.Monitor {
    public void monitor() {
        Binder.blockUntilThreadAvailable();
    }
}

blockUntilThreadAvailable 最终调用的是 IPCThreadState,等待有空闲的 binder 线程

IPCThreadState.cpp

void IPCThreadState::blockUntilThreadAvailable()
{
    pthread_mutex_lock(&mProcess->mThreadCountLock);
    while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) {
        //等待正在执行的binder线程小于进程最大binder线程上限(16个)
        pthread_cond_wait(&mProcess->mThreadCountDecrement,
            &mProcess->mThreadCountLock);
    }
    pthread_mutex_unlock(&mProcess->mThreadCountLock);
}

可见 addMonitor(new BinderThreadMonitor()) 最终的目标是将 Binder 线程添加到 android.fg 线程的handler(mMonitorChecker) 来检查是否工作正常。

2.4 init

Watchdog.java

public void init(Context context, ActivityManagerService activity) {
    mActivity = activity;
    //注册reboot广播接收者
    context.registerReceiver(new RebootRequestReceiver(),
            new IntentFilter(Intent.ACTION_REBOOT),
            android.Manifest.permission.REBOOT, null);
}

2.4.1 RebootRequestReceiver

final class RebootRequestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context c, Intent intent) {
        if (intent.getIntExtra("nowait", 0) != 0) {
            rebootSystem("Received ACTION_REBOOT broadcast");
            return;
        }
        Slog.w(TAG, "Unsupported ACTION_REBOOT broadcast: " + intent);
    }
}

2.4.2 rebootSystem

void rebootSystem(String reason) {
    Slog.i(TAG, "Rebooting system because: " + reason);
    IPowerManager pms = (IPowerManager)ServiceManager.getService(
        Context.POWER_SERVICE);
    try {
        //通过PowerManager执行reboot操作
        pms.reboot(false, reason, false);
    } catch (RemoteException ex) {
    }
}

最终是通过 PowerManagerService 来完成重启操作,具体的重启流程后续会单独讲述。

三 Watchdog检测机制

当调用 watchdog.start() 时,则进入线程 “watchdog” 的 run() 方法,该方法分成两部分:

  • 前半部,用于监测是否触发超时
  • 后半部,当触发超时则输出各种信息

3.1 run

public void run() {
        boolean waitedHalf = false;
        while (true) {
            final List<HandlerChecker> blockedCheckers;
            final String subject;
            final boolean allowRestart;
            int debuggerWasConnected = 0;
            synchronized (this) {
                long timeout = CHECK_INTERVAL;//CHECK_INTERVAL=30s
                //每30s轮询所有的monitor
                for (int i=0; i<mHandlerCheckers.size(); i++) {
                    HandlerChecker hc = mHandlerCheckers.get(i);
//执行所有的Checker的监控方法, 每个Checker记录当前的mStartTime
                    hc.scheduleCheckLocked();
                }

                if (debuggerWasConnected > 0) {
                    debuggerWasConnected--;
                }
                // positive on when to kill things.
                long start = SystemClock.uptimeMillis();
                //通过循环,保证执行30s才会继续往下执行
                while (timeout > 0) {
                    if (Debug.isDebuggerConnected()) {
                        debuggerWasConnected = 2;
                    }
                    try {
                        wait(timeout);//触发中断,直接捕获异常,继续等待.
                    } catch (InterruptedException e) {
                        Log.wtf(TAG, e);
                    }
                    if (Debug.isDebuggerConnected()) {
                        debuggerWasConnected = 2;
                    }
                    timeout = CHECK_INTERVAL - 
                        (SystemClock.uptimeMillis() - start);
                }

                boolean fdLimitTriggered = false;
                if (mOpenFdMonitor != null) {
                    fdLimitTriggered = mOpenFdMonitor.monitor();
                }

                if (!fdLimitTriggered) {//评估monitor完成状态,并做相应操作
                    //评估Checker状态
                    final int waitState = evaluateCheckerCompletionLocked();
                    if (waitState == COMPLETED) {
                        //已完成,跳过
                        waitedHalf = false;
                        continue;
                    } else if (waitState == WAITING) {
                        //waiting状态,但并未超过timeout
                        continue;
                    } else if (waitState == WAITED_HALF) {
                        if (!waitedHalf) {
                            Slog.i(TAG, "WAITED_HALF");
                            //首次进入等待时间过半的状态
             //block 30s时候先dump一次system_server和一些native的 stack
                        ArrayList<Integer> pids = new ArrayList<Integer>();
                        pids.add(Process.myPid());
                        //输出system_server和3个native进程的traces
                        ActivityManagerService.dumpStackTraces(pids, null, null,
                            getInterestingNativePids());
                        waitedHalf = true;
//waitedHalf这个变量保证下一次过来还是当前状态不用dump堆栈,交给下面部分去dump.
                        }
                        continue;
                    }

                    // 如果状态是 overdue!,也就是超过60秒
                    //获取卡住60s的hanlerchecker
                    blockedCheckers = getBlockedCheckersLocked();
                    subject = describeCheckersLocked(blockedCheckers);
                } else {
                    blockedCheckers = Collections.emptyList();
                    subject = "Open FD high water mark reached";
                }
                allowRestart = mAllowRestart;
            }

        //代码执行到这里说明此时system_server中的监控线程已经卡住并且超过60s,
		//此时会dump堆栈并kill system_server 然后restart
            EventLog.writeEvent(EventLogTags.WATCHDOG, subject);

            ArrayList<Integer> pids = new ArrayList<>();
            pids.add(Process.myPid());
            if (mPhonePid > 0) pids.add(mPhonePid);
            //dump即将被kill进程的堆栈
            final File stack = ActivityManagerService.dumpStackTraces(
                    pids, null, null, getInterestingNativePids());
            //多留一点时间保证dump信息可以保存完整
            SystemClock.sleep(5000);
//触发内核来dump所有被block的线程,并输出所有CPU上堆栈到kernel log中
            doSysRq('w');
            doSysRq('l');
            //Try to add the error to the dropbox        
            Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
                public void run() {
                    if (mActivity != null) {
                        mActivity.addErrorToDropBox(
                        "watchdog", null, "system_server", null, null, null,
                        subject, null, stack, null);
                    }
                }
            };
            dropboxThread.start();
            try {
                // wait up to 2 seconds for it to return.
                dropboxThread.join(2000);  
            } catch (InterruptedException ignored) {}

            IActivityController controller;
            synchronized (this) {
                controller = mController;
            }
            if (controller != null) {
                Slog.i(TAG, "Reporting stuck state to activity controller");
                try {
                    Binder.setDumpDisabled("Service dumps disabled due"+
                    "to hung system process.");
                    // 1 = keep waiting, -1 = kill system
                    int res = controller.systemNotResponding(subject);
                    if (res >= 0) {
          Slog.i(TAG, "Activity controller requested to coninue to wait");
                        waitedHalf = false;
                        continue;
                    }
                } catch (RemoteException e) {
                }
            }

            // Only kill the process if the debugger is not attached.
            if (Debug.isDebuggerConnected()) {
                debuggerWasConnected = 2;
            }
            if (debuggerWasConnected >= 2) {
                Slog.w(TAG, "Debugger connected: Watchdog is *not* "+
                "killing the system process");
            } else if (debuggerWasConnected > 0) {
                Slog.w(TAG, "Debugger was connected: Watchdog is *not* " +
                "killing the system process");
            } else if (!allowRestart) {
                Slog.w(TAG, "Restart not allowed: Watchdog is *not* "+
                "killing the system process");
            } else {
                Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + subject);
                WatchdogDiagnostics.diagnoseCheckers(blockedCheckers);
                Slog.w(TAG, "*** GOODBYE!");
                // kill 掉system_server
                Process.killProcess(Process.myPid());
                System.exit(10);
            }

            waitedHalf = false;
        }
    }

这个方法是 watchdog 监控的核心:

1.执行所有的 Checker 的监控方法 scheduleCheckLocked()

  • 当 mMonitor 个数为 0 (除了 android.fg 线程之外都为 0) 且处于 poll 状态,则设置 mCompleted = true
  • 当上次 check 还没有完成,则直接返回

2.等待 30s 后,再调用 evaluateCheckerCompletionLocked 来评估 Checker 状态
3.根据 waitState 状态来执行不同的操作

  • 当 COMPLETED 或 WAITING,则相安无事
  • 当 WAITED_HALF (超过30s) 且为首次,则输出 system_server 和3个 Native 进程的 traces
  • 当 OVERDUE,则 dump 更多信息

4.Watchdog 检测到异常的信息收集

  • AMS.dumpStackTraces:输出Java和Native进程的栈信息
  • doSysRq
  • dropBox

收集完信息后便会杀死 system_server 进程。此处 allowRestart 默认值为 true,当执行 am hang 操作则设置不允许重启 (allowRestart =false), 则不会杀死 system_server 进程。

由此可见当触发一次 Watchdog,则必然会调用两次 AMS.dumpStackTraces,也就是说 system_server 和3个 Native 进程的 traces 信息会输出两遍,且时间间隔超过 30s。

3.2 scheduleCheckLocked

public final class HandlerChecker implements Runnable {
    ......
    public void scheduleCheckLocked() {
        if (mCompleted) {
                // Safe to update monitors in queue
                // Handler is not in the middle of work
                mMonitors.addAll(mMonitorQueue);
                mMonitorQueue.clear();
        }
        if ((mMonitors.size() == 0 &&
            mHandler.getLooper().getQueue().isPolling()) ||
            (mPauseCount > 0)) {
            mCompleted = true; //当目标looper正在轮询状态则返回。
            return;
        }

        if (!mCompleted) {
            return; //有一个check正在处理中,则无需重复发送
        }
        mCompleted = false;

        mCurrentMonitor = null;
        // 记录当下的时间
        mStartTime = SystemClock.uptimeMillis();
        //发送消息,插入消息队列最开头, 见下方的run()方法
        mHandler.postAtFrontOfQueue(this);
    }

    public void run() {
        final int size = mMonitors.size();
        for (int i = 0 ; i < size ; i++) {
            synchronized (Watchdog.this) {
                mCurrentMonitor = mMonitors.get(i);
            }
            //回调具体服务的monitor方法
            mCurrentMonitor.monitor();
        }

        synchronized (Watchdog.this) {
            mCompleted = true;
            mCurrentMonitor = null;
        }
    }
}

该方法主要功能:向 Watchdog 的监控线程的消息队列的最头部发送本 HandlerChecker 任务,并执行该 HandlerChecker 的 run() 方法,在该方法中调用 monitor(),执行完成后会设置 mCompleted = true。当 handler 消息池无法处理当前的消息,导致迟迟没有机会执行 monitor() 方法,则会触发 watchdog。

其中 postAtFrontOfQueue(this),该方法输入参数为 Runnable 对象,根据消息机制, 最终会回调 HandlerChecker 中的 run 方法,该方法会循环遍历所有的 Monitor 接口,具体的服务实现该接口的 monitor() 方法。

可能存在的问题:如果有其他消息不断地调用 postAtFrontOfQueue() 也可能导致 watchdog 没有机会执行;或者是每个 monitor 消耗一些时间,累加起来超过1分钟造成的 watchdog。这些都是非常规的 Watchdog。

3.3 evaluateCheckerCompletionLocked

private int evaluateCheckerCompletionLocked() {
    int state = COMPLETED;
    for (int i=0; i<mHandlerCheckers.size(); i++) {
        HandlerChecker hc = mHandlerCheckers.get(i);
        state = Math.max(state, hc.getCompletionStateLocked());
    }
    return state;
}


public int getCompletionStateLocked() {
    if (mCompleted) {
        return COMPLETED;
    } else {
        long latency = SystemClock.uptimeMillis() - mStartTime;
        // mWaitMax默认是60s
        if (latency < mWaitMax/2) {
            return WAITING;
        } else if (latency < mWaitMax) {
            return WAITED_HALF;
        }
    }
    return OVERDUE;
}

获取 mHandlerCheckers 列表中等待状态值最大的 state。

  • COMPLETED = 0:等待完成
  • WAITING = 1:等待时间小于 DEFAULT_TIMEOUT 的一半,即 30s
  • WAITED_HALF = 2:等待时间处于 30s~60s 之间
  • OVERDUE = 3:等待时间大于或等于 60s

3.4 getBlockedCheckersLocked

获取卡住 60s 的 hanlerchecker

private ArrayList<HandlerChecker> getBlockedCheckersLocked() {
    ArrayList<HandlerChecker> checkers = new ArrayList<HandlerChecker>();
    for (int i=0; i<mHandlerCheckers.size(); i++) {
        HandlerChecker hc = mHandlerCheckers.get(i);
		//将所有没有完成,且超时的checker加入队列
        if (hc.isOverdueLocked()) {
            checkers.add(hc);
        }
    }
    return checkers;
}

boolean isOverdueLocked() {
     return (!mCompleted) &&
     (SystemClock.uptimeMillis() > mStartTime + mWaitMax);
}

3.5 describeCheckersLocked

private String describeCheckersLocked(List<HandlerChecker> checkers) {
        StringBuilder builder = new StringBuilder(128);
        for (int i=0; i<checkers.size(); i++) {
            if (builder.length() > 0) {
                builder.append(", ");
            }
            // 输出所有的checker信息
            builder.append(checkers.get(i).describeBlockedStateLocked());
        }
        return builder.toString();
}

public String describeBlockedStateLocked() {   
   if (mCurrentMonitor == null) {//非前台线程进入该分支
       return "Blocked in handler on " + mName +
        " (" + getThread().getName() + ")";   
   } else {//前台线程进入该分支
       return "Blocked in monitor " +
        mCurrentMonitor.getClass().getName()
               + " on " + mName + " (" + getThread().getName() + ")";
   }
}

将所有执行时间超过1分钟的 handler 线程或者 monitor 都记录下来。

  • Blocked in handler,意味着相应的线程处理当前消息时间超过1分钟
  • Blocked in monitor,意味着相应的线程处理当前消息时间超过1分钟,或者 monitor 迟迟拿不到锁

四 总结

Watchdog 是一个运行在 system_server 进程的名为 ”watchdog” 的线程:

  • Watchdog 运作过程,当阻塞时间超过1分钟则触发一次 watchdog,会杀死 system_server,触发上层重启
  • mHandlerCheckers 是记录所有的 HandlerChecker 对象的列表,包括 foreground,main,ui,i/o,display 线程的 handler
  • mHandlerChecker.mMonitors 记录所有 Watchdog 目前正在监控 Monitor,所有的这些 monitors 都运行在 foreground 线程
  • 有两种方式加入 Watchdog 监控:
  1. addThread():用于监测 Handler 线程,默认超时时长为 60s。这种超时往往是所对应的 handler 线程消息处理得慢
  2. addMonitor():用于监控实现了 Watchdog.Monitor 接口的服务。这种超时可能是 ”android.fg” 线程消息处理得慢,也可能是 monitor 迟迟拿不到锁

以下情况,即使触发了 Watchdog,也不会杀掉 system_server 进程:

  • monkey:设置 IActivityController,拦截 systemNotResponding 事件,比如 monkey
  • hang:执行 am hang 命令,不重启
  • debugger:连接 debugger 的情况,不重启

4.1 监控Handler线程

Watchdog 监控的线程有:

默认地 DEFAULT_TIMEOUT=60s,调试时才为 10s 方便找出潜在的 ANR 问题。

线程名 对应handler 说明 Timeout
main new Handler(Looper.getMainLooper()) 当前主线程 1min
android.fg FgThread.getHandler 前台线程 1min
android.ui UiThread.getHandler UI线程 1min
android.io IoThread.getHandler I/O线程 1min
android.display DisplayThread.getHandler display线程 1min
ActivityManager AMS.MainHandler AMS线程 1min
PowerManagerService PMS.PowerManagerHandler PMS线程 1min
PackageManager PermissionManagerService.mHandler PMS线程 1min
PackageManager PKMS.PackageHandler PKMS线程 10min
RollbackManagerServiceHandler RollbackManagerService.mHandlerThread RMS线程 10min

在目前的 android 10.0 中 watchdog 会监控 system_server 进程中的以上 10 个线程:

  • 前8个线程的 Looper 消息处理时间不得超过1分钟
  • PackageManager 和 RollbackManagerServiceHandler 线程的处理时间不得超过10分钟

4.2 监控同步锁

能够被 Watchdog 监控的系统服务需要实现 Watchdog.Monitor 接口,并实现其中的 monitor() 方法。运行在 android.fg 线程,系统中实现该接口类主要有:

  • ActivityManagerService
  • WindowManagerService
  • TvRemoteService
  • InputManagerService
  • PowerManagerService
  • StorageManagerService
  • BinderThreadMonitor
  • MediaProjectionManagerService
  • MediaRouterService
  • MediaSessionService

4.3 输出信息

watchdog 在 check 过程中出现阻塞 1 分钟的情况,则会输出:

1.AMS.dumpStackTraces:输出 system_server 和3个native 进程的 traces

  • 该方法会输出两次,第一次在超时 30s 的地方;第二次在超时 1min

2.doSysRq,触发 kernel 来 dump 所有阻塞线程,输出所有 CPU 的 backtrace 到 kernel log

  • 通过向节点 /proc/sysrq-trigger 写入字符

3.dropBox,输出文件到 /data/system/dropbox,内容是 trace + blocked 信息

4.杀掉 system_server,进而触发 zygote 进程自杀,从而重启上层 framework

你可能感兴趣的:(Android,framework)