Android 12 Watchdog 介绍与启动

Posted pecuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 12 Watchdog 介绍与启动相关的知识,希望对你有一定的参考价值。

文章托管在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);

以上是关于Android 12 Watchdog 介绍与启动的主要内容,如果未能解决你的问题,请参考以下文章

Android 12 Watchdog 工作流程

Android 12 Watchdog 工作流程

Android 进阶——系统启动之SystemServer进程创建并启动Watchdog 监听系统服务详解

Android 进阶——系统启动之SystemServer进程创建并启动Watchdog 监听系统服务详解

Android 进阶——SystemServer进程启动之Watchdog 详解

Android 12 Watchdog 案例分析集