这篇主要讲StartService的主要逻辑 Api-27
启动Service首先会进入Context.mBase的startService().mBase就是ContextImpl. 接着进入ContextImpl.startService()
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());
...
}
}
复制代码
然后ContextImpl.startServiceCommon(),通过ActivityManager.getService().startService()返回ActivityManagerService在客户端的Binder句柄就开始进行进程间通信了。 来看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 {
1. 通过retrieveServiceLocked得到service的信息
ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
...
ServiceRecord r = res.record;
...
2. Android8.0新增的用于限制启动后台Service的操作
if (!r.startRequested && !fgRequired) {
final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
r.appInfo.targetSdkVersion, callingPid, false, false);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
if (allowed == ActivityManager.APP_START_MODE_DELAYED) {
return null;
}
UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);
return new ComponentName("?", "app is in background uid " + uidRec);
}
}
...
final ServiceMap smap = getServiceMapLocked(r.userId);
...
3.
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
复制代码
这个方法做的事情是:
- 通过传过来的Intent获取要启动的Service信息retrieveServiceLocked().这个方法会从ServiceMap里找内存中已经运行的Service,如果没找到就通过Intent让PackageManagerService帮忙找对应的Service信息.
- 这一段逻辑是Android8.0新增的,主要用于限制后台Service启动Service.详情请看这篇文章Android Bug分析之8.0的后台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;
}
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
}
复制代码
bringUpServiceLocked主要逻辑如下
- 首先判断当前Service是不是已经运行. r.app.thread这是个IApplicationThread的引用,也就是ActivityThread的Binder句柄,如果这个不为空那就说明service已经运行,那就sendServiceArgsLocked()去执行Service的onStartCommand(),返回.
- 查找Service需要运行的进程是否存在,如果存在了就调用realStartServiceLocked()去启动Service,如果不存在那就把进入3
- 调用AMS.startProcessLocked()去启动相应的进程,如果进程启动失败了就去调用bringDownServiceLocked(r),停止该Service的启动,否则就把要启动的Service信息加到mPendingServices里面去.启动进程是个异步操作,在启动完成之前,会把要启动的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);
...
}
复制代码
我们回到步骤2里看下真正启动Service的方法readStartServiceLocked()
ActiveServices:
try {
...
1.
app.thread.scheduleCreateService()
...
}
...
2.
sendServiceArgsLocked(r, execInFg, true);
复制代码
简单来说就两步
- 创建Service:app.thread.scheduleCreateService().这里会调用生成Service的代码ActivityThread.handleCreateService(),完成onCreate()的回调
ActivityThread:
private void handleStopActivity(IBinder token, boolean show, int configChanges, int seq) {
1.通过反射生成Service对象
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
}
try {
2.完成Service信息的注册并回调onCreate()
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
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);
}
...
}
复制代码
- 然后sendServiceArgsLocked调用Service.onStartCommand()
ActivityThread:
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
...
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
}
try {
ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
}
...
}
}
}
复制代码
最终调用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()启动过程已经分析完了