startService笔记
ContextImpl
1、startService
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
2、startServiceCommon
Android 5.0
开始不允许隐式启动Service
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
//如果SDK 版本大于LOLLIPOP 的,要求service 不能隐式启动。
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
//远程调用AMS服务
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
// ...
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
AMS
1、startService
@Override
public ComponentName startService(...)
throws TransactionTooLargeException {
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
//通过ActiveService启动
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
ActiveService
1、startServiceLocked
ComponentName startServiceLocked(...)
throws TransactionTooLargeException {
//调用同名方法startServiceLocked
return startServiceLocked(...);
}
2、startServiceLocked
ComponentName startServiceLocked(...)
throws TransactionTooLargeException {
//主要做了一些参数过滤
//调用startServiceInnerLocked
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
3、startServiceInnerLocked
ComponentName startServiceInnerLocked(...) throws TransactionTooLargeException {
//调用bringUpServiceLocked
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
return r.name;
}
4、bringUpServiceLocked
这个方法主要有三个分支
- 1、
Service
已经create
过了,再次调用只会触发sendServiceArgsLocked
从而回调onStartCommand
- 2、
Service
没有create
过,但是目标进程存在,则创建进程后再创建Service
- 3、
Service
的目标进程不存在,这里就会先创建进程、创建Application
、创建Service
,因为步骤和Activity的启动流程相差无几
,所以这里不再赘述本分支
//判断是否有ProcessRecord,没有的话则通过AMS创建进程,有的话调
//用
private String bringUpServiceLocked(...){
//分支1
//该service 已经create,再次调用startService() 函数的时
//候,会直接调用sendServiceArgsLocked()
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
//...
//分支2
//如果service 的ProcessRecord 已经创建了,会直接调用
//realStartServiceLocked(),进入start service 的最终流程
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {
try {
//调用realStartServiceLocked
realStartServiceLocked(r, app, execInFg);
return null;
}
}
}
//分支3
//如果service 还没有create,会调用AMS 中startProcessLocked() 创建
if (app == null && !permissionsReviewRequired) {
//创建进程、进而创建Application
if ((app=mAm.startProcessLocked(...)) == null) {
//...
}
}
return null;
}
分支1
1、sendServiceArgsLocked
在
Service
已经create
的情况下,会调用该方法,这里主要做了两件事:
- 1、发送
ANR
消息- 2、调用
ActivityThread
的scheduleServiceArgs
去触发onStartCommand
/**
1、每次startService,都会对应一次onStartCommand,就算Service已经onCreate成功。
2、Service的回调函数都是在主线程,
**/
private final void sendServiceArgsLocked(...){
//这里处理超时
bumpServiceExecutingLocked(r, execInFg, "start");
//1、调用ActivityThread的scheduleServiceArgs
//2、ActivityThread通过Handler发送消息调用handleServiceArgs
//重要!!!这也就是为什么每次startService都会回调一次onStartCommand
try {
r.app.thread.scheduleServiceArgs(r, slice);
}
}
ActivityThread
2、handleServiceArgs
r.app.thread.scheduleServiceArgs
主要通过Handler
触发handleServiceArgs
在这里面做了几件主要的事情:
- 1、回调
onStartCommand
- 2、调用
AMS
方法serviceDoneExecuting
,在方法里面remove
掉ANR
消息。值得留意的是serviceDoneExecuting
是一个oneway
方法,说明它不会阻塞客户端
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
data.args.prepareToEnterProcess();
}
int res;
if (!data.taskRemoved) {
//重要
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
}
} catch (Exception e) {
}
}
}
分支2
ActiveService
1、realStartServiceLocked
在
Service
没有创建过的情况下,会做以下几件事情:
- 1、处理
ANR
- 2、
app.thread.scheduleCreateService
通过Handler
触发- 3、因为不满足条件,所以进入
requestServiceBindingsLocked
后不会调用onBind
- 4、调用
sendServiceArgsLocked
回调onStartCommand
,因为这部分代码分支1
已经贴出,这里就不再贴了
private final void realStartServiceLocked(...) {
//这里创建了一个ServiceRecord
r.setProcess(app);
final boolean newService = app.services.add(r);
//处理超时
bumpServiceExecutingLocked(r, execInFg, "create");
//...
boolean created = false;
try {
//1、继续通过ActivityThread发送消息,去回调OnCreate
app.thread.scheduleCreateService(...);
} catch (DeadObjectException e) {}
//这一行代码是bindService的流程,但是因为r.bindingSize < 0,所以并不会
//真正执行onBind
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
//回调onStartCommand
sendServiceArgsLocked(r, execInFg, true);
}
ActivityThread
1、handleCreateService
在这里面主要做了几件事:
- 1、创建
Service
- 2、创建
Service
的ContextImpl
- 3、回调
Service
的attach
和onCreate
- 4、告诉
AMS
服务已经创建完毕,remove ANR
消息
接着还会调用
realStartServiceLocked
里面的sendServiceArgsLocked
去回调onStartCommand
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
}
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);
}
}
}
分支3
创建进程和
Application
后再创建Service
,这里不再赘述
总结
整体流程
- 1、通过
ContextImpl
调用到AMS
的启动方法- 2、
AMS
将逻辑交给ActiveService处理
- 3、
ActiveService
在bringUpServiceLocked
分三种情况
- (1)
Service
已经Create
过:回调Service
的onStartCommand
- (2)
Service
没有Create
过,但目标进程存在:回调Service
的onCreate
和onStartCommand
- (3)
Service
的目标进程不存在:创建进程和Application
后再创建Service
,接着回调Service
的onCreate
和onStartCommand
时序图
欠着先,打扰了…