这篇主要讲startService的启动过程。API-27
普通启动Service首先会进入Context.mBase的startService().mBase就是ContextImpl.
接着进入ContextImpl.startService()
然后ContextImpl.startServiceCommon(),通过ActivityManager.getService().startService()返回ActivityManagerService在客户端的Binder句柄就开始进行进程间通信了。
ContextImpl:
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {
try {
...
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
...
}
}
来看ActivityManagerService.startService()
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
...
synchronized(this) {
...
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
这里的mServices就是AMS中封装启动Service操作的ActiveServices类,相对应的Activity的是ActivityStarter类.
然后就调用ActiveServices的startServiceLocked()去启动Service。我们来看:
ActiveService:
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
...//通过retrieveServiceLocked得到service的信息
ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
...
ServiceRecord r = res.record;
...
final ServiceMap smap = getServiceMapLocked(r.userId);
...
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
这个方法主要做两个操作:
1.通过传过来的Intent获取要启动的Service信息()---retrieveServiceLocked()
2.把获取的信息交给startServiceInnerLocked()去继续启动.
先来看retrieveServiceLocked
ActiveService:
private ServiceLookupResult retrieveServiceLocked(Intent service,
String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
//拿到smap
ServiceMap smap = getServiceMapLocked(userId);
//拿到我们传入的ComponentName(比如new Intent(this, xxxService.class))
final ComponentName comp = service.getComponent();
if (comp != null) {
//第一次这个r肯定是null的
r = smap.mServicesByName.get(comp);
if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by component: " + r);
}
if (r == null && !isBindExternal) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
//这个也是null的
r = smap.mServicesByIntent.get(filter);
if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by intent: " + r);
}
//
if (r == null) {
try {
//这句是通过PackageManager去解析AndroidManifest找到对应的Service
ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
resolvedType, ActivityManagerService.STOCK_PM_FLAGS
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
userId, callingUid);
...
r = smap.mServicesByName.get(name);
if (r == null && createIfNeeded) {
...
r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
res.setService(r);
//这两个SparseArray终于有值了
smap.mServicesByName.put(name, r);
smap.mServicesByIntent.put(filter, r);
...
}
}
}
//正常情况下r终于不是null了因为之前的createIfNeed默认是true
if (r != null) {
//一些权限检查
...
return new ServiceLookupResult(r, null);
}
}
retrieveServiceLocked的逻辑分为以下几个步骤.
1.这里首先获取一个ServiceMap,这个ServiceMap是Handler的子类,他的两个重要成员ArrayMap
2.如果第一步没有获取到,那就mServicesByIntent获取
3.如果是第一次启动这个Service那么前两步肯定是获取不到的,那现在就会调用PackageManagerService去获取配置在AndroidManifest里面的Service信息.
在第三步之后就把ServiceRecord加入到mServicesByName和mServicesByIntent里了。
拿到Service信息后就继续调用startServiceInnerLocked()进行启动.
ActiveServices:
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
...
}
startServiceInnerLocked()主要是去调用bringUpServiceLocked().
ActiveServices.bringUpServiceLocked:
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//1.
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
...
//2.
if (!isolated) {
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(r, app, execInFg);
return null;
}
...
}
}
//3.
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked()) == null) {
bringDownServiceLocked(r);
return msg;
}
}
...
//4.
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
}
我这里分为四个步骤去解释bringUpServiceLocked
1.首先如果是r.app.thread这是个IApplicationThread的引用,也就是ActivityThread的Binder句柄,如果这个不为空那就说明service已经运行,那就sendServiceArgsLocked()去执行Service的onStartCommand(),返回.
2.查找Service需要运行的进程是否存在,如果存在了就调用realStartServiceLocked()去启动Service,如果不存在那就进入3
3.调用AMS.startProcessLocked()去启动相应的进程,启动进程的逻辑以后会写的,[埋个坑].
4.启动进程是个异步操作,在启动完成之前,会把要启动的Service信息放在mPengingServices里,将来进程启动完成会调用ActivityThread.attach()然后调用AMS.attachApplication()方法,最终会进入ActiveServices.attachApplicationLocked()找到mPengingServices里存着的要启动的Service进行启动.
ActiveServices:
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
sr = mPendingServices.get(i);
mPendingServices.remove(i);
realStartServiceLocked(sr, proc, sr.createdFromFg);
...
}
下面来看真正启动Service的方法readStartServiceLocked()
ActiveServices:
try {
...
app.thread.scheduleCreateService()
...
}
...
sendServiceArgsLocked(r, execInFg, true);
简单来说就两步
1.创建Service:app.thread.scheduleCreateService()
2.然后sendServiceArgsLocked调用onStartCommand():app.thread.scheduleServiceArgs()
创建Service是通过app.thread这个ActivityThread的Binder句柄执行scheduleCreateService()执行过程和生成Activity很像
ActivityThread:
private class ApplicationThread extends IApplicationThread.Stub {
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);
}
}
public void handleMessage(Message msg) {
...
case CREATE_SERVICE:
handleCreateService((CreateServiceData)msg.obj);
...
}
private void handleCreateService(CreateServiceData data) {
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
}
...
try {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService());
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
最终调用handleCreateService生成Service,然后attach()然后执行onCreate();
scheduleCreateService()也是差不多流程,通过调用AMS的handleServiceArgs()
private void handleServiceArgs(ServiceArgsData data) {
try {
...
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
...
try {
ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
至此,startService()启动过程已经分析完了
最后附上我过源码分析的思维导图
出现的一些类的定义:
类名 | 定义 |
---|---|
ActiveServices | 负责创建Service |
ServiceMap | 是一个Handler的子类,负责查找相应的Service |
ServiceRecord | 描述了Service组件的信息 |