文章目录
回顾
Activity启动系列总结:
Activity启动流程总结-ActivityThread
Activity启动流程总结-生命周期
Activity启动流程总结-超时判定机制
在Activity启动流程中对APP进程和ActivityManagerService的交互过程以及应用进程启动初始化过程做了简单总结。Service作为四大组件之一,它的启动过程大体相似。
概述
在开发中我们使用context.startService(intent)和context.stopService(intent)来启动和停止Service,Service的启动和停止也是由ActivityManagerService来进行调度,本文通过跟踪源码来看看它的启动和停止过程。
源码探究
文中源码基于 Android 10.0
startService过程
当执行context.startService(intent),将开始Service的启动过程:
[ContextImpl#startService]
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
public ComponentName startForegroundService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, true, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
// ···
// 请求AMS启动Service
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
if (cn != null) {
// 省略检查异常部分 ···
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
可以看到通过IActivityManager调用ActivityManagerService进行startService。
接下来从APP进程来到ActivityManagerService:
[ActivityManagerService#startService]
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
// 省略参数异常检查 ···
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
// mServices实例是ActiveServices
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
该方法中调用ActiveServices的startServiceLocked方法进一步处理。
ActiveServices的startServiceLocked方法中又调用了另一个重载方法:
[ActiveServices#startServiceLocked]
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
final int userId, boolean allowBackgroundActivityStarts)
throws TransactionTooLargeException {
// 省略变量callerFg部分(用于标记调用方进程是否属于前台)···
// 查找或新建可用ServiceRecord
ServiceLookupResult res =
retrieveServiceLocked(service, null, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
// 省略对res结果检查部分 ···
ServiceRecord r = res.record;
// 省略后台启动检查和启动权限检查部分 ···
// 创建startCommand参数添加到pendingStarts集合中保存
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants, callingUid));
// 调用startServiceInnerLocked进一步处理
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
这里获取一个ServiceRecord(被包装在ServiceLookupResult中),ServiceRecord用于保存Service信息,一个ServiceRecord对应一个运行Service。然后调用startServiceInnerLocked方法进一步执行启动流程。
retrieveServiceLocked方法中,首先获取userId对应的ServiceMap缓存集合,根据ComponentName(显式意图)或IntentFilter(隐式意图)查找ServiceRecord。不存在的话,则从PackageManagerService查找匹配的ServiceInfo,之后创建ServiceRecord并保存在集合中。在返回结果前还会判断是否允许不同应用和不同userId间的调用和启动权限检查。
接下来进入startServiceInnerLocked方法:
[ActiveServices#startServiceInnerLocked]
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
// ···
// 进一步执行启动
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
// 省略添加后台启动服务集合和启动前台服务判断部分 ···
return r.name;
}
进入bringUpServiceLocked方法:
[ActiveServices#bringUpServiceLocked]
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
// 判断目标Service是否已启动,首次将要启动时ServiceRecord中还未设置IApplicationThread
if (r.app != null && r.app.thread != null) {
// 调度应用进程触发onStartCommand回调
sendServiceArgsLocked(r, execInFg, false);
return null;
}
// 判断目标Service是否等待重启
if (!whileRestarting && mRestartingServices.contains(r)) {
// If waiting for a restart, then do nothing.
return null;
}
// ···
// 重置目标Service的延迟启动标识 ···
// 检查目标Service的userId对应用户是否已启动 ···
// ···
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
f