前言
Service啟動與上一篇說的入口Activity啟動類似,主要分成ContextImpl到ActivityManagerService調(diào)用和ActivityThread啟動Service這兩個過程
ContextImpl到AMS的調(diào)用過程
這個過程比較簡單,如圖所示

啟動Service肯定是從startService開始,這個方法是在ContextWrapper中實現(xiàn)的,在這個方法中調(diào)用了ContextImpl的startService方法。
在ContextImpl中經(jīng)過startServiceCommon,最終通過IActivityManager的startService方法來通知AMS啟動一個Service。
ActivityThread啟動Service
這部分過程如圖:

上一個過程最終是調(diào)用了AMS的startService方法,這個過程就是從這開始的,這里會調(diào)用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方法會先查找參數(shù)service對應(yīng)的ServiceRecord;如果沒有回調(diào)用PackageManagerService取獲取參數(shù)service對應(yīng)的Service信息并封裝到ServiceRecord。最后將ServiceRecord封裝成ServiceLookupResult返回??梢钥吹竭@里與上一篇講的Activity很類似,ServiceRecord就像ActivityRecord一樣用來描述一個Service。
代碼2就是從ServiceLookupResult取出ServiceRecord,然后調(diào)用startServiceInnerLocked。
startServiceInnerLocked方法會調(diào)用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調(diào)用AMS的getProcessRecordLocked查詢與該Service對應(yīng)的ProcessRecord,ProcessRecord一看名字就應(yīng)該能猜出來了,主要是描述運行的應(yīng)用程序進程信息。所以代碼2的目的就是獲取該Service對應(yīng)的應(yīng)用程序進程。
代碼3處判斷如果應(yīng)用程序進程存在,則執(zhí)行代碼4,通過realStartServiceLocked方法來啟動Service。
如果不存在就會跳到代碼5,再次判斷不存在則在代碼6處調(diào)用AMS的startProcessLocked來創(chuàng)建對應(yīng)的應(yīng)用程序信息。
在realStartServiceLocked方法中調(diào)用了IApplicationThread的scheduleCreateService方法,它的實現(xiàn)是ActivityThread內(nèi)部類ApplicatioinThread,這塊跟Activity啟動幾乎一樣。
scheduleCreateService將service的啟動參數(shù)封裝后通過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信息,創(chuàng)建service;代碼4獲取上下文;代碼5通過service的attach方法來初始化service;代碼6則調(diào)用了service的onCreate方法;代碼7將service加入ActivithThread的成員變量mServices中,以便后續(xù)使用。