(点击上方公众号,可快速关注)
来源:伯乐在线专栏作者 - gityuan
链接:http://android.jobbole.com/84881/
点击 → 了解如何加入专栏作者
一、概述
Android系统中,有硬件WatchDog用于定时检测关键硬件是否正常工作,类似地,在framework层有一个软件WatchDog用于定期检测关键系统服务是否发生死锁事件。WatchDog功能主要是分析系统核心服务和重要线程是否处于Blocked状态。
监视reboot广播;
监视mMonitors关键系统服务是否死锁。
二、启动流程
2.1 startOtherServices
[-> SystemServer.java]
private void startOtherServices() {
...
//创建watchdog【见小节2.2】
final Watchdog watchdog = Watchdog.getInstance();
//注册reboot广播【见小节2.3】
watchdog.init(context, mActivityManagerService);
...
mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
...
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
...
// watchdog启动【见小节3.1】
Watchdog.getInstance().start();
mSystemServiceManager.startBootPhase(
SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
}
}
}
2.2 getInstance
[-> Watchdog.java]
public static Watchdog getInstance() {
if (sWatchdog == null) {
//单例模式,创建实例对象【见小节2.2.1 】
sWatchdog = new Watchdog();
}
return sWatchdog;
}
2.2.1 创建Watchdog
[-> Watchdog.java]
public class Watchdog extends Thread {
...
private Watchdog() {
super("watchdog");
//【见小节2.2.2 】
mMonitorChecker = new HandlerChecker(FgThread.getHandler(),
"foreground thread", DEFAULT_TIMEOUT);
mHandlerCheckers.add(mMonitorChecker);
mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()),
"main thread", DEFAULT_TIMEOUT));
mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(),
"ui thread", DEFAULT_TIMEOUT));
mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),
"i/o thread", DEFAULT_TIMEOUT));
mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
"display thread", DEFAULT_TIMEOUT));
//【见小节2.2.3】
addMonitor(new BinderThreadMonitor());
}
}
Watchdog继承于Thread,创建的线程名为”watchdog”。mHandlerCheckers是记录着所有的HandlerChecker对象的列表。
Watchdog监控的线程有:
线程名 | 对应handler | 含义 |
---|
main thread | new Handler(MainLooper) | 当前主线程 |
android.fg | FgThread.getHandler | 前台线程 |
android.ui | UiThread.getHandler | UI线程 |
android.io | IoThread.getHandler | I/O线程 |
android.display | DisplayThread.getHandler | Display线程 |
DEFAULT_TIMEOUT默认为60s,调试时才为10s方便找出潜在的ANR问题。
2.2.2 HandlerChecker
[-> Watchdog.java]
public final class HandlerChecker implements Runnable {
...
HandlerChecker(Handler handler, String name, long waitMaxMillis) {
mHandler = handler;
mName = name;
mWaitMax = waitMaxMillis;
mCompleted = true;
}
}
mMonitors记录所有Watchdog目前正在监控的服务。
2.2.3 监控Binder线程
在小节【2.2.1】创建Watchdog时,通过addMonitor(new BinderThreadMonitor())来监控Binder线程, 这里拆分两步骤:
addMonitor
new BinderThreadMonitor
2.2.3.1 addMonitor
public class Watchdog extends Thread {
public void addMonitor(Monitor monitor) {
synchronized (this) {
if (isAlive()) {
throw new RuntimeException("Monitors can't be added once the Watchdog is running");
}
//此处mMonitorChecker数据类型为HandlerChecker
mMonitorChecker.addMonitor(monitor);
}
}
public final class HandlerChecker implements Runnable {
private final ArrayList mMonitors = new ArrayList();
public void addMonitor(Monitor monitor) {
//将上面的BinderThreadMonitor添加到mMonitors队列
mMonitors.add(monitor);
}
...
}
}
将monitor添加到HandlerChecker的成员变量mMonitors列表中。
2.2.3.2 BinderThreadMonitor
private static final class BinderThreadMonitor implements Watchdog.Monitor {
public void monitor() {
Binder.blockUntilThreadAvailable();
}
}
blockUntilThreadAvailable最终调用的是IPCThreadState,等待有空闲的binder线程
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.2.4 Monitor
public class Watchdog extends Thread {
public interface Monitor {
void monitor();
}
}
能够被Watchdog监控的系统服务都实现了Watchdog.Monitor接口。 实现该接口类:
2.3 init
[-> Watchdog.java]
public void init(Context context, ActivityManagerService activity) {
mResolver = context.getContentResolver();
mActivity = activity;
//注册reboot广播接收者【见小节2.3.1】
context.registerReceiver(new RebootRequestReceiver(),
new IntentFilter(Intent.ACTION_REBOOT),
android.Manifest.permission.REBOOT, null);
}
2.3.1 RebootRequestReceiver
[-> Watchdog.java]
final class RebootRequestReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context c, Intent intent) {
if (intent.getIntExtra("nowait", 0) != 0) {
//【见小节2.3.2】
rebootSystem("Received ACTION_REBOOT broadcast");
return;
}
Slog.w(TAG, "Unsupported ACTION_REBOOT broadcast: " + intent);
}
}
2.3.2 rebootSystem
[-> Watchdog.java]
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来完成重启操作,具体的重启流程后续会单独讲述。
2.4 小节
获取watchdog实例对象,并注册reboot广播
mHandlerCheckers记录所有的HandlerChecker对象的列表,包括foreground, main, ui, i/o, display线程的handler;
mMonitors记录所有Watchdog目前正在监控Monitor,此处为BinderThreadMonitor;
注册reboot广播,最终是通过PowerManagerService来完成;
系统每间隔1分钟,执行一次monitor操作, 当系统hang时间超过1分钟则执行run()方法;
下面来看看当系统hang超过1分钟时,进入watchdog.run()的过程:
三、Watchdog
3.1 run
public void run() {
boolean waitedHalf = false;
while (true) {
final ArrayList blockedCheckers;
final String subject;
final boolean allowRestart;
int debuggerWasConnected = 0;
synchronized (this) {
//timeout=30s
long timeout = CHECK_INTERVAL;
for (int i=0; imHandlerCheckers.size(); i++) {
HandlerChecker hc = mHandlerCheckers.get(i);
//【见小节3.2】
hc.scheduleCheckLocked();
}
if (debuggerWasConnected > 0) {
debuggerWasConnected--;
}
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);
}
接下文
专栏作者简介( 点击 → 加入专栏作者 )
gityuan:Android全栈工程师:上至能写App,中间能改framework和Native代码,下至能调驱动,全栈能解决性能与稳定性。(新浪微博:@Gityuan)
打赏支持作者写出更多好文章,谢谢!
关注「安卓开发精选」
看更多精选安卓技术文章
↓↓↓