Android 11 Service启动流程分析
上一篇我们介绍了Activity启动流程,接下来的这一篇我们接着分析一下Service的启动流程。不了解Activity的启动流程的可以看我的这篇文章Android 11 Activity启动流程分析。本篇文章是基于android11源码来分析的。
Service启动流程调用时序图
service启动流程源码分析
首先,我们在启动一个服务时会在Activity中调用startService方法,它的实现在ContextWrapper中,代码如下:
public class ContextWrapper extends Context {
Context mBase;
...
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
...
}
还记得在上一片文章中我们介绍的Activity的启动流程,会调用到ActivityThread的performLaunchActivity方法,在这个方法中会对上下文进行初始化赋值。不太了解的可以查看我的这篇文章Android 11 Activity启动流程分析。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
if (activity != null) {
ContextImpl appContext = createBaseContextForActivity(r);//1
...
}
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
...
}
return activity;
}
在注释1处创建了上下文对象appContext,这个上下文就是ContextImpl,然后再通过activity的attach方法把appContext赋值给ContextWrapper的mBase成员变量。所以接下来我们应该看ContextImpl中的startService方法。
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
...
//1
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
getOpPackageName(), getAttributionTag(), user.getIdentifier());
...
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
startService中会return一个startServiceCommon方法,这个方法内部又调用了ActivityManagerService的startService方法。接下来我们就要关注ActivityManagerService是怎么启动的Service。
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage,
String callingFeatureId, int userId)
throws TransactionTooLargeException {
...
synchronized(this) {
...
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, callingFeatureId, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
这里调用了ActiveServices的startServiceLocked方法,代码如下:
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
@Nullable String callingFeatureId, final int userId,
boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
...
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
...
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
...
return r.name;
}
在startServiceLocked内部调用了自己的startServiceInnerLocked方法,而startServiceInnerLocked方法又调用了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;
}
...
final String procName = r.processName;//1
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
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.longVersionCode, 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.shortInstanceName, e);
}
}
} else {
app = r.isolatedProc;
...
}
if (app == null && !permissionsReviewRequired) {//5
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {//6
...
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
...
return null;
}
在注释1处得到ServiceRecord的processName的值赋值给procName ,其中processName用来描述Service想要在哪个进程运行,默认是当前进程,我们也可以在AndroidManifes配置文件中设置android:process属性来新开启一个进程运行Service。注释2处将procName和Service的uid传入到AMS的getProcessRecordLocked方法中,来查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来记录运行的应用程序进程的信息。注释5处判断两个条件一个是当前Service的进程是否不存在,另一个是需不需要检查权限。这两个条件满足后,就会调用注释6处的AMS的startProcessLocked方法创建一个指定进程。注释3处判断所需的应用进程存在,那么就直接调用realStartServiceLocked方法来启动服务。代码如下:
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
boolean created = false;
try {
...
//1
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app, "Died when creating service");
throw e;
}
...
sendServiceArgsLocked(r, execInFg, true);//2
...
}
注释1处realStartServiceLocked会调用 app.thread的scheduleCreateService,完成Service创建和onCreate方法的回调工作。其中app.thread其实指的就是IApplicationThread的类型的aidl接口,其实现类是ActivityThread的内部类ApplicationThread,而ApplicationThread又继承自IApplicationThread.Stub,这个IApplicationThread.Stub类继承自Binder并实现了IApplicationThread接口的抽象类。注释2处会调sendServiceArgsLocked方法用来处理启动服务后的后续操作,比如Service的回调onStartCommand方法,接下来我们看一下ApplicationThread的scheduleCreateService方法。
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
这里它封装了一个CreateServiceData对象然后传给了sendMessage方法并想H这个Handler类发送了一条CREATE_SERVICE消息。然后在H类的handleMessage方法中进行了处理。这个流程和Activity的启动流程是类似的。接下来我们主需要看handleMessage方法中对应的CREATE_SERVICE消息的处理。
public void handleMessage(Message msg) {
...
case CREATE_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
("serviceCreate: " + String.valueOf(msg.obj)));
}
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
这里可以看到它调用了ActivityThread的handleCreateService方法
@UnsupportedAppUsage
private void handleCreateService(CreateServiceData data) {
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);//1
Service service = null;
try {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);//2
Application app = packageInfo.makeApplication(false, mInstrumentation);
java.lang.ClassLoader cl = packageInfo.getClassLoader();//3
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);//4
context.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());//5
service.onCreate();//6
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
...
}
} catch (Exception e) {
...
}
}
首先通过注释1处获取要启动Service应用程序的LoadedApk 对象,LoadedApk其实就是一个apk信息的封装类。然后通过注释2处创建Service所需的上下文对象ContextImpl ,接着在注释3处获取LoadedApk 的类加载器ClassLoader,接着通过类加载器和Service信息把Service加载到内存并创建一个实例,然后在注释5处调用service的attach方法关联上下文环境context和做些初始化工作,紧接着调用service的onCreate方法服务正式启动。Service启动后就会进行后续操作会调用ActiveServices的sendServiceArgsLocked方法
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
...
try {
r.app.thread.scheduleServiceArgs(r, slice);
} catch (TransactionTooLargeException e) {
...
}
...
}
这里调用了app.thread的scheduleServiceArgs方法,这里和启动服务调用方式是一样的会调用到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);
}
}
这里还是通过Handler发送了一个SERVICE_ARGS消息,然后到handleMessage会调用ActivityThread的handleServiceArgs方法
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
...
int res;
if (!data.taskRemoved) {
//1
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
...
} catch (Exception e) {
...
}
}
}
在这个方法内部我们就可以看到我们在开发中常常会复写的Service的方法onStartCommand了。到这里Service的启动流程也就结束了,其实到Servcie的onCreate被调用时Service的启动流程就已经结束了。这里只是为了说明一下onStartCommand到底是在哪被调用的。