一、Service生命周期
首先我们先回忆一下Service的声明周期
image- 第一次调用startServie(): Service.onCreate()->Service.onStartCommand()
- 第二次调用startService(): Service.onStartCommand()
本周主要分析上面两步操作,Service的启动行为。
二、Service启动分析
image阶段一:app进程startService(),向SystemServer进程发送启动Service的请求
首先明确一点,启动Service、启动Activity、发送广播,这些都是Context上下文的本职工作。
在Applciation、Activity或者Service中都可以调用startService(),最终会调用到ContextImpl.startService()
- ContextImpl.StartService
- ContextImpl.startServiceCommon
- ActivityManager.getService().startService()
阶段二:SystemService进程 处理启动Service请求
在ActivityManagerService中,启动service的操作 是委托给ActiveServices执行的。
- ActivityManagerService.startService()
- ActiveServices.startServiceLocked()
startServiceLocked方法中会解析要启动的Service,创建对应的ServiceRecord实例,最终调用自身bringUpServiceLocked方法。
## ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
//(1)解析、创建响应的ServiceRecord
ServiceLookupResult res =retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
ServiceRecord r = res.record;
//(2)调用内部方法
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
- ActiveServices.startServiceInnerLocked()
- ActiveServices.bringUpServiceLocked()
bringUpServiceLocked是处理Service启动逻辑的核心方法。
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//注释一:如果Service已经创建,则直接调用sendServiceArgsLocked(),最终会触发Service.onStartCommand()方法调用
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
if (!isolated) {
//注释二:非独立进程,则直接启动Service:onCreate(),onStartCommad()方法
realStartServiceLocked(r, app, execInFg);
}else {
//注释三: 如果Service要运行独立进程,且进程不存在,则创建新进程.
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
}
}
- 注释一:如果Service已经创建,则直接调用sendServiceArgsLocked(),最终调用Service.onStartCommand()方法。对应第二次调用StartService方法的场景,此场景Service仅会回调onStartCommand()回调
- 注释二:如果Service不要求运行在新的进程,则调用realStartServiceLocked()方法,该方法 会触发Service.onCreate()和onStartCommand()方法
- 注释三: 如果Service要运行独立进程,且进程不存在,则创建新进程.
阶段三:ActivityMangaerService 与 ActivityThread IPC互动过程。
下面我们一起来看一下ActiveServices是 如何创建,并启动Service的。
核心方法在realStartServiceLocked()
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
//(1)向ApplicationThread发送消息,创建Service
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
//(2)向Service发送参数
sendServiceArgsLocked(r, execInFg, true);
}
1、scheduleCreateService
利用ApplicationThread 向app进程发送IPC消息
- ApplicationThread.scheduleCreateService()
- ApplicationThread发送H.CREATE_SERVICE消息
- ActivityThread.handleCreateService()
private void handleCreateService(CreateServiceData data) {
//(1)创建Service
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
//(2)创建ContextImpl
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
//(3)调用Service.attah()
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//(4)调用Service.onCreate()
service.onCreate();
}
handleCreateService()中完成了以下操作:
- 利用LoaedApk创建了Service实例,
- 创建ContextImpl()实例
- 调用Service.attach()完成ContextImpl的绑定
- 调用Service.onCreate()方法
2、 sendServiceArgsLocked 启动Service的参数处理
ActiveServices.sendServiceArgsLocked 主要做的操作就是,通过ApplicationThread发送scheduleServiceArgs的IPC消息
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,boolean oomAdjusted) throws TransactionTooLargeException {
r.app.thread.scheduleServiceArgs(r, slice);
}
- ApplicationThread.scheduleServiceArgs()
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
List<ServiceStartArgs> list = args.getList();
for (int i = 0; i < list.size(); i++) {
ServiceStartArgs ssa = list.get(i);
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = ssa.taskRemoved;
s.startId = ssa.startId;
s.flags = ssa.flags;
s.args = ssa.args;
sendMessage(H.SERVICE_ARGS, s);
}
}
- 发送H.SERVICE_ARGS 消息
- ActivityThread.handleServiceArgs(),调用Service.onStartCommand()
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
}
三、参考文章
https://www.jianshu.com/p/cc25fbb5c0b3
https://www.jianshu.com/p/e65cfcbdd11e
网友评论