一、前言
ANR⼤致划分为Service、Broadcast、InputDispatch、Provider四中类型,下⾯⼀
⼀解释他们各⾃的监测原理。本篇我们将集合源码,对四种ANR类型中的Service类型的触发机制做详尽的介绍。
二、Service Timeout
Service Timeout是位于”ActivityManager”线程中的ActivityManagerService.MainHandler收到 SERVICE_TIMEOUT_MSG 或 者 SERVICE_FOREGROUND_TIMEOUT_MSG 消息时触发。
⾸先,AMS初始化时,启动了⼀个THREAD_PRIORITY_FOREGROUND优先级
的ServiceThread,mHandler运⾏在这个线程:
public ActivityManagerService(Context systemContext) {
...
//ServiceThread 是⼀个HandlerThread
mHandlerThread = new ServiceThread(TAG,
THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
..
}
三、 Service 设置定时器
service 启动时就⼀句话, startService 或者 binderService() ,关于Service的启
动流程,这⾥不做详细分析,简单介绍⼀下。
startService最终调⽤到AMS,
- AMS通过Socket通信⽅式向Zygote进程请求⽣成(fork)⽤于承载服务的进程,并
且初始化ActivityThread对象。ActivityThread是应⽤程序的主线程; - Zygote通过fork的⽅法,将zygote进程复制⽣成新的进程,并将ActivityThread
相关的资源加载到新进程; - ActivityManagerService向新⽣成的ActivityThread进程,通过Binder⽅式发送
⽣成服务的请求; - ActivityThread通过反射的⽅式创建RemoteService
在service启动的流程中,会在Service进程attach到system_server进程的过程最终会
调⽤ realStartServiceLocked() ,发送延迟消息,设置 定时器 ,
realStartServiceLocked 主要有如下两件事情:
【1】post 延迟消息
【2】调⽤service的onCreate⽅法
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
//...省略...
//【1】post 延迟消息
bumpServiceExecutingLocked(r, execInFg, "create");
boolean created = false;
try {
//【2】调⽤service的onCreate⽅法
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.application
Info),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service
" + r);
mAm.appDiedLocked(app);
throw e;
} finally {
if (!created) {
//...
serviceDoneExecutingLocked(r, inDestroying,
inDestroying);
//..
}
}
//...省略...
}
接下来看bumpServiceExecutingLocked ⽅法,调⽤
scheduleServiceTimeoutLocked 发送延迟消息,并且根据service前后台的属性,来决
定TIMEOUT的时间.
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final void bumpServiceExecutingLocked(ServiceRecord r,
boolean fg