1.启动的入口startservice
无论怎么样,Activity的startservice最终都会到,ActivityManagerService的startService,函数中来。
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {
synchronized (this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
而这个函数并没有做太多事情,就调用了mServices.startServiceLocked,这个mServices变量子在ams里面是专门用来管理service的。
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {
....
ServiceLookupResult res =
retrieveServiceLockedWrapper(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
if (res == null) {
return null;
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
这里主要做了两件事情
- retrieveServiceLockedWrapper : 建立service信息
- startServiceInnerLocked: 启动这个service
2.service信息的建立过程 — retrieveServiceLocked
private ServiceLookupResult retrieveServiceLockedWrapper(Intent service,
String resolveType, String callingPackage, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
ServiceLookupResult res = retrieveServiceLocked(service, resolveType, callingPackage,
callingPid, callingUid, userId, createIfNeeded, callingFromFg, isBindExternal);
String targetPackageName = null;
if (res != null && res.record != null) {
targetPackageName = res.record.packageName;
}
return res;
}
继续调用retrieveServiceLocked
private ServiceLookupResult retrieveServiceLocked(Intent service,
String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
ServiceRecord r = null;
userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
ServiceMap smap = getServiceMap(userId);
final ComponentName comp = service.getComponent();
if (comp != null) {
r = smap.mServicesByName.get(comp);
}
...
if (r == null) {
try {
ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service,
resolvedType, ActivityManagerService.STOCK_PM_FLAGS
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
userId);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
": not found");
return null;
}
ComponentName name = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
...
r = smap.mServicesByName.get(name);
if (r == null && createIfNeeded) {
Intent.FilterComparison filter
= new Intent.FilterComparison(service.cloneFilter());
ServiceRestarter res = new ServiceRestarter();
BatteryStatsImpl.Uid.Pkg.Serv ss = null;
BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
ss = stats.getServiceStatsLocked(
sInfo.applicationInfo.uid, sInfo.packageName,
sInfo.name);
}
r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
res.setService(r);
smap.mServicesByName.put(name, r);
smap.mServicesByIntent.put(filter, r);
...
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}
if (r != null) {
if (mAm.checkComponentPermission(r.permission,
callingPid, callingUid, r.appInfo.uid, r.exported)
....
}
if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid,
resolvedType, r.appInfo)) {
return null;
}
return new ServiceLookupResult(r, null);
}
return null;
}
- 1、通过getServiceMap获取 smap 这个是一个全局的收集Service的地方,
- 2、comp 如果是第一次启动service是空,如果不是的话就不会
- 3、这个rServiceRecord,如果是第一次的话也是空
- 4、如果空怎么办呢?去pms里面找,如果没有找到,rinfo是空的就返回空如果找到,就new一个comp,然后在做一个sInfo复制给r。
- 5、然后这个r就有了,然后就返回new ServiceLookupResult(r, null);
- 6、其他就是权限检查
这样子,我们就建立了一个service的信息。ServiceRecord会放在ServiceMap中。
3.service的启动过程 —startServiceInnerLocked
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
}
r.callStart = false;
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
return r.name;
}
将刚才的r,以及其他的信息放给bringUpServiceLocked.
bringUpServiceLocked
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
...
}
} else {
...
app = r.isolatedProc;
}
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", 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 (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
- 一开始判断你这个r是否已经有了app,如果你已经知道了就直接sendServiceArgsLocked 这里第一次是不会的,也就对应我们的service的onCreate只会执行一次,就下面realStartServiceLocked
- 这里判断是不是isolated 如果不是就直接realStartServiceLocked。如果是就还要绕一大圈。
- 记住这个mPendingServices
过程大概是:
1、startProcessLocked 启动进程,然后会加载一个新的ActivityThread,
2、然后就会application.attach 就会回到我们AMS的attachApplication
3、AMS 的 attachApplication 实际上是 attachApplicationLocked
4、然后又最终我们的ActiveServices 的attachApplicationLocked 如下
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mPendingServices.remove(i);
i--;
proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
mAm.mProcessStats);
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
if (!isServiceNeeded(sr, false, false)) {
// We were waiting for this service to start, but it is actually no
// longer needed. This could happen because bringDownServiceIfNeeded
// won't bring down a service that is pending... so now the pending
// is done, so let's drop it.
bringDownServiceLocked(sr);
}
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortName, e);
throw e;
}
}
mPendingServices 是我们刚才记住的。
最终还是会调用realStartServiceLocked
所以在bringUpServiceLocked里面很重要,
- 1、它判断了你的所要启动的service是否已经有了进程
- 2、是否你所要启动的service是不是单独的一个孤立进程
- 3、如果没有进程我还需要给你需要启动的service记录下来,为你启动一个进程,然后等你进程起来以后再给你启动serivice
4.最后回调给应用realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
//妈的这里壁纸怎么还特殊处理
if (mAm.mWallpaperClassName != null && r.name.equals(mAm.mWallpaperClassName)) {
mAm.mWallpaperProcess = app;
}
final boolean newService = app.services.add(r);
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
mAm.updateOomAdjLocked();
boolean created = false;
try {
....
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
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 (r.whitelistManager) {
app.whitelistManager = true;
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
...
sendServiceArgsLocked(r, execInFg, true);
...
}
- 1、调用你所需要启动的service的onCreat
- 2、sendServiceArgsLocked 这个就是发送onStartCommand
具体怎么调用过去需要看ams和app直接binder的接口流程。
这样你的service就起来了。