Service一般会有两种状态,启动状态,通过startService启动,一般用于后台计算,另一种是绑定状态,通过bindService启动,用于和其他组件和Service进行通信.两种状态可以共存,可以startService之后又bindService
startService启动流程图
图1-1 startService启动流程startService启动流程分析
1. startService执行在ContextWrapper中,mBase的类型是ContextImpl.通过上次Activity启动流程的分析,在Activity创建过程中会通过activity.attach方法与ContextImpl关联,ContextWrapper内部大部分方法都是通过mBase实现,所以startService其实是执行在ContextImpl内部,startService会调用内部的startServiceCommon方法,最终会调用到AMS中的startService方法
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
...
//调用了AMS的startService方法
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
...
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
2.AMS中startService方法又调用了startServiceLocked方法,startServiceLocked最后会执行startServiceInnerLocked方法,但是在startServiceInnerLocked并没有完成具体的启动工作,而是再调用了bringUpServiceLocked方法,
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
...
synchronized(this) {
...
try {
//调用了内部的startServiceLocked
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
...
//调用startServiceInnerLocked
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
//调用bringUpServiceLocked
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
...
}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
...
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
//调用realStartServiceLocked
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
...
}
2.1在bringUpServiceLocked中,调用realStartServiceLocked,最后在realStartServicdeLocked中会调用IApplicationThread的scheduleCreateService方法,IApplicationThread在前一篇中也分析过,所以最终会调用到ActivityThread中ApplicationThread的scheduleCreateService方法
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
...
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);
}
3.熟悉的handler处理消息,调用handleCreateService方法
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
//反射生成service对象
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
...
//调用service的onCreate方法
service.onCreate();
...
3.1 在bringUpServiceLocked的方法中,还会调用一个sendServiceArgsLocked的方法,这个会调用到ApplicationThread中的scheduleServiceArgs方法,最终会在service的onStartCommand方法中回调
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
...
if (r.app != null && r.app.thread != null) {
//调用方法ApplicationThread方法
sendServiceArgsLocked(r, execInFg, false);
return null;
}
...
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处理消息
case SERVICE_ARGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
handleServiceArgs((ServiceArgsData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
最后回调Service的onStartCommond方法
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
...
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
}
...
}
网友评论