前言

复杂的东西往往很难掌握,但是我们可以把问题进行拆解,拆解成一个个容易理解的小模块,当每个小模块都掌握后,整个大模块也就迎刃而解了。

本章主要讲解WatchDog的启动流程,把整个启动脉络理清楚,具体详细的分析会单独开新的章节梳理。

SystemServer启动时会在startBootstrapServices中启动WatchDog并进行初始化,如下:

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");
        // 1. WatchDog使用了单利模式,必然调用了构造函数
        final Watchdog watchdog = Watchdog.getInstance();
        // 2. 调用start()方法
        watchdog.start();
        t.traceEnd();
        ......
        t.traceBegin("InitWatchdog");
        // 3. 调用init方法
        watchdog.init(mSystemContext, mActivityManagerService);
        t.traceEnd();
        ......
    }

下面对关键步骤1,2,3进行分析。

Watchdog.getInstance()

// 很简单的单例模式
    public static Watchdog getInstance() {
        if (sWatchdog == null) {
            sWatchdog = new Watchdog();
        }

        return sWatchdog;
    }
    // 继续看下构造函数
    private Watchdog() {
    	// 1. 初始化mThread线程
        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.
        // 2. 初始化mMonitorChecker和mHandlerCheckers,这两个后面详细分析
        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));
        // 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.
        // 3. 将一个BinderThreadMonitor对象添加到Monitor中,这个函数我们后面章节详细分析
        addMonitor(new BinderThreadMonitor());

		// 4. mInterestingJavaPids是一个ArrayList,目前为空,这里加入第一个元素
        mInterestingJavaPids.add(Process.myPid());

        // See the notes on DEFAULT_TIMEOUT.
        // 5. DEFAULT_TIMEOUT必须大于WRAPPED_PID_TIMEOUT_MILLIS(默认30毫秒),后面会详细分析DEFAULT_TIMEOUT的逻辑
        assert DB ||
                DEFAULT_TIMEOUT > ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS;

		// 6. 初始化mTraceErrorLogger,内部使用了Trace来记录日志
        mTraceErrorLogger = new TraceErrorLogger();
    }

可以看出,在WatchDog的构造函数中,主要进行了一些初始化动作,我们重点关注的对象有mThread、mMonitorChecker和mHandlerCheckers。

private final Thread mThread;
    private final ArrayList<HandlerChecker> mHandlerCheckers = new ArrayList<>();
    private final HandlerChecker mMonitorChecker;
    // HandlerChecker是一个Runnable对象
    public final class HandlerChecker implements Runnable {

WatchDog.start()

public void start() {
        mThread.start();
    }

start函数启动了mThread线程,此时必然会调用run函数。

watchdogd 触发 android 安卓 watchdog_framework


这里是WatchDog的核心部分,代码量占到了整个类的四分之一左右。可以看到,整个函数跑在一个死循环当中,waitedHalf初始值为false。这个run函数大概180多行,我们后面章节详细分析。

WatchDog.init

public void init(Context context, ActivityManagerService activity) {
        mActivity = activity;
        context.registerReceiver(new RebootRequestReceiver(),
                new IntentFilter(Intent.ACTION_REBOOT),
                android.Manifest.permission.REBOOT, null);
    }

注册了一个监听广播Intent.ACTION_REBOOT的广播,mActivity为ActivityManagerService,所有init函数必须要等AMS注册完成才能调用。看下Receiver的实现:

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);
        }
    }

nowait参数不等于0时调用rebootSystem函数:

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

可以看到直接调用了PMS的reboot函数。

目前没有找到发送广播并且nowait为1的地方,能想到的一个使用场景是系统进程或者系统应用拥有android.Manifest.permission.REBOOT权限的可以通过发送这个广播实现重启系统的功能。

本章完