前言
Service启动与上一篇说的入口Activity启动类似,主要分成ContextImpl到ActivityManagerService调用和ActivityThread启动Service这两个过程
ContextImpl到AMS的调用过程
这个过程比较简单,如图所示
启动Service肯定是从startService开始,这个方法是在ContextWrapper中实现的,在这个方法中调用了ContextImpl的startService方法。
在ContextImpl中经过startServiceCommon,最终通过IActivityManager的startService方法来通知AMS启动一个Service。
ActivityThread启动Service
这部分过程如图:
上一个过程最终是调用了AMS的startService方法,这个过程就是从这开始的,这里会调用ActiveService的startServiceLocked,代码如下:
ComponentName startServiceLocked(...) throws TransactionTooLargeException {
...
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false); //1
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record; //1
...
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
代码1处通过retrieveServiceLocked方法会先查找参数service对应的ServiceRecord;如果没有回调用PackageManagerService取获取参数service对应的Service信息并封装到ServiceRecord。最后将ServiceRecord封装成ServiceLookupResult返回。可以看到这里与上一篇讲的Activity很类似,ServiceRecord就像ActivityRecord一样用来描述一个Service。
代码2就是从ServiceLookupResult取出ServiceRecord,然后调用startServiceInnerLocked。
startServiceInnerLocked方法会调用bringUpServiceLocked方法,这个方法代码如下:
private String bringUpServiceLocked(...) throws TransactionTooLargeException {
...
final String procName = r.processName; //1
String hostingType = "service";
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); //2
...
if (app != null && app.thread != null) { //3
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg); //4
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
}
} else {
...
}
if (app == null && !permissionsReviewRequired) { //5
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, //6
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;
}
}
...
return null;
}
代码1得到进程名称。代码2调用AMS的getProcessRecordLocked查询与该Service对应的ProcessRecord,ProcessRecord一看名字就应该能猜出来了,主要是描述运行的应用程序进程信息。所以代码2的目的就是获取该Service对应的应用程序进程。
代码3处判断如果应用程序进程存在,则执行代码4,通过realStartServiceLocked方法来启动Service。
如果不存在就会跳到代码5,再次判断不存在则在代码6处调用AMS的startProcessLocked来创建对应的应用程序信息。
在realStartServiceLocked方法中调用了IApplicationThread的scheduleCreateService方法,它的实现是ActivityThread内部类ApplicatioinThread,这块跟Activity启动几乎一样。
scheduleCreateService将service的启动参数封装后通过Handler进行通知。最终会在ActivityThread处理,处理方法是handleCreateService,代码如下:
private void handleCreateService(CreateServiceData data) {
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo); //1
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader(); //2
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent); //3
} catch (Exception e) {
...
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);//4
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService()); //5
service.onCreate(); //6
mServices.put(data.token, service); //7
...
} catch (Exception e) {
...
}
}
代码2会获取类加载器,然后代码3从之前封装的对象中获取Service信息,创建service;代码4获取上下文;代码5通过service的attach方法来初始化service;代码6则调用了service的onCreate方法;代码7将service加入ActivithThread的成员变量mServices中,以便后续使用。