文章托管在gitee上 Android Notes , 同步csdn
Watchdog 介绍
Watchdog的功能实际上是一个监控程序,用于监测系统进程运行状态,以确保系统处于正常运转状态。当系统关键线程出现卡住或其他一些异常情况发生时,一些系统关键服务可能无法正常工作,当卡住过长时间时,Watchdog会重启系统(框架层面),以确保用户能够正常使用设备。
Watchdog的功能大致如下:
- 监听系统关键Handler是否能及时处理消息,实际上是判断其关联的线程是否卡住
- 监听系统Binder线程是否异常,是否处于starve状态
- 监听系统关键服务是否出现了死锁超时或者执行调用卡住长期持锁
当等待恢复时间超时一半,则会输出系统关键进程的trace文件;当等待完全超时时,输出系统关键进程的trace、binder调用信息、输出kernel的堆栈信息、输出Dropbox信息(data/system/dropbox)等,在新版本的Watchdog实现,会将前后两个trace合并为一个新的完整的trace。当等待超过最大时间,则会kill系统进程,zygote也会重启;如果是monkey测试,根据monkey测试输入的命令可以选择继续等待。
SystemServer#startBootstrapServices
在系统启动之初,在startBootstrapServices方法中创建Watchdog,并调用其start方法
/**
* Starts the small tangle of critical services that are needed to get the system off the
* ground. These services have complex mutual dependencies which is why we initialize them all
* in one place here. Unless your service is also entwined in these dependencies, it should be
* initialized in one of the other functions.
*/
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("startBootstrapServices");
// Start the watchdog as early as possible so we can crash the system server
// if we deadlock during early boot
t.traceBegin("StartWatchdog");
final Watchdog watchdog = Watchdog.getInstance();
watchdog.start();
t.traceEnd();
...
}
Watchdog#getInstance
Watchdog使用单例模式创建,在系统进程中唯一
public static Watchdog getInstance() {
if (sWatchdog == null) {
sWatchdog = new Watchdog();
}
return sWatchdog;
}
Watchdog构造
- 创建内部线程,用于执行监控工作
- 创建多个HandlerChecker,用于监控多个线程是否卡住
- 监控FgThread的HandlerChecker是通用的MonitorChecker,可以添加AMS,WMS等监控
private Watchdog() {
// Watchdog内部工作线程,用于执行监控工作,在run方法中执行
mThread = new Thread(this::run, "watchdog");
// Initialize handler checkers for each common thread we want to check. Note
// that we are not currently checking the background thread, since it can
// potentially hold longer running operations with no guarantees about the 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 = new HandlerChecker(FgThread.getHandler(),
"foreground thread", DEFAULT_TIMEOUT); // 监控fg线程
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));// 监控ui线程
// And also check IO thread.
mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),
"i/o thread", DEFAULT_TIMEOUT));// 监控io线程
// And the display thread.
mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
"display thread", DEFAULT_TIMEOUT));// 监控display线程
// And the animation thread.
mHandlerCheckers.add(new HandlerChecker(AnimationThread.getHandler(),
"animation thread", DEFAULT_TIMEOUT));// 监控animation线程
// And the surface animation thread.
mHandlerCheckers.add(new HandlerChecker(SurfaceAnimationThread.getHandler(),
"surface animation thread", DEFAULT_TIMEOUT));// 监控surface animation线程
// Initialize monitor for Binder threads.
addMonitor(new BinderThreadMonitor());// 监控binder线程
mInterestingJavaPids.add(Process.myPid());//添加兴趣pid,出现hung时会dump进程的stack
// See the notes on DEFAULT_TIMEOUT.
assert DB ||
DEFAULT_TIMEOUT > ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS;
mTraceErrorLogger = new TraceErrorLogger();
}
Watchdog#start
在创建Watchdog后,会调用其start方法来启动其工作线程,并执行监控工作. start方法直接调用了其内部线程的start方法,启动线程之后调用Watchdog的run方法,具体工作在run方法中执行.
/**
* Called by SystemServer to cause the internal thread to begin execution.
*/
public void start() {
mThread.start();
}
添加监控
// Note: This method is invoked on the main thread but may need to attach various
// handlers to other threads. So take care to be explicit about the looper.
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
...
mHandlerThread = new ServiceThread(TAG,
THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
...
Watchdog.getInstance().addMonitor(this); // 添加AMS到监控队列
Watchdog.getInstance().addThread(mHandler); // 添加线程到Watchdog监控列表mHandlerCheckers
...
}
Watchdog#init
在SystemServer#startBootstrapServices中,在AMS启动完成并注册为binder服务后,会调用Watchdog#init来完成它的启动。
// Complete the watchdog setup with an ActivityManager instance and listen for reboots
// Do this only after the ActivityManagerService is properly started as a system process
t.traceBegin("InitWatchdog");
watchdog.init(mSystemContext, mActivityManagerService);
t.traceEnd();
该init方法使得Watchdog持有AMS引用,以方便来调用AMS相关的方法完成一些特定功能。另外,注册ACTION_REBOOT广播,以便触发reboot。
/**
* Registers a {@link BroadcastReceiver} to listen to reboot broadcasts and trigger reboot.
* Should be called during boot after the ActivityManagerService is up and registered
* as a system service so it can handle registration of a {@link BroadcastReceiver}.
*/
public void init(Context context, ActivityManagerService activity) {
mActivity = activity;
context.registerReceiver(new RebootRequestReceiver(),
new IntentFilter(Intent.ACTION_REBOOT),
android.Manifest.permission.REBOOT, null);
}