考察内容:
service启动有哪几种方式? service启动过程中主要流程有哪些? service启动过程涉及哪些参与者,通信过程是怎样的? Service启动原理 用startService启动Service:@Override
public ComponentName startService(Intent service) {
return startServiceCommon(service, mUser);
}
ComponentName startServiceCommon(Intent service, ...){
ComponentName cn = ActivityManagerNative.getDefault()
.startService(mMainThread.getApplicationThread(), service, ...);
return cn;
}
AMS中的处理:
ComponentName startService(IApplicationThread caller, Intent service, ...){
ComponentName res = mServices.startServiceLocked(caller, service, ...);
return res;
}
根据intent 查询service Record对象:
每个应用端的Service在AMS中都对应一个ServiceRecore对象
ComponentName startServiceLocked(Intent service, ...){
ServiceLookupResult res = retrieveServiceLocked(service, ...);
ServiceRecord r = res.record;
...
//查到ServiceRecord之后new了一个StartItem并加到pendingStart里面,
//为后面调用onStartCommand准备
r.pendingStart.add(new ServiceRecord.StartItem(r, ...));
...
return startServiceInnerLocked(smap, service, r, ...);
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ...){
bringUpServiceLocked(r, service.getFlags(), callerFg, false);
}
final String bringUpServiceLocked(ServiceRecord r, ...){
if(r.app != null && r.app.thread != null) {
//如果Service已经启动了,就调用下面这个函数,
//它将触发应用端的onStartCommand
sendServiceArgsLocked(r, ...);
return null;
}
//Service还没启动的情况:
ProcessRecord app = mAm.getProcessRecordLocked(procName, ...);
if(app != null && app.thread != null){
//如果Service所在的进程已经启动了,真正启动Service
//r.app就是在下面这个函数中设置的
realStartServiceLocked(r, app, execInFg);
return null;
}
//Service所在进程没有启动或者虽然已经启动但还没就绪的情况:
if(app == null){
//app进程还没启动,启动进程
app = mAm.startProcessLocked(procName, ...);
}
if(!mPendingServices.contains(r)){
//把ServiceRecord加到pending列表里面,等待进程启动后再处理
mPendingServices.add(r);
}
...
}
进程启动的流程图:
boolean attachApplicationLocked(IApplicationThread thread, ...) {
...
mServices.attachApplicationLocked(app, processName);
...
return true;
}
//处理pending的Service
boolean attachApplicationLocked(ProcessRecord proc, ...){
for(int i = 0; i < mPendingServices.size(); i++){
sr = mPendingServices.get(i);
...
mPendingServices.remove(i--);
//对每一个pending的service调用realStartServiceLocked函数真正启动service
realStartServiceLocked(sr, proc, ...);
}
...
}
void realStartServiceLocked(ServiceRecord r, ProcessRecord app, ...){
r.app = app;
...
//向应用端发起IPC调用,应用收到后就会创建Service,执行应用里的onCreate回调
//参数r其实是一个binder对象: final class ServiceRecord extends Binder{}
//这是要存在应用端的,应用端有一个用来保存service对象的map,这里的r就是key
app.thread.scheduleCreateService(r, r.serviceInfo, ...);
...
//触发应用端Service的onStartCommand
sendServiceArgsLocked(r, ...);
}
应用端是如何处理AMS发过来的CreateServicd请求的:
private void handleCreateService(CreateServiceData data){
//先拿到loadedApk
LoadedApk packageInfo = getPackageInfoNoCheck(...);
//加载Service类,并通过newInstance调用其构造函数,从而获得Service对象
Service service = (Service)cl.loadClass(data.info.name).newInstance();
//给这个Service创建一个Context对象
ContextImpl context = ContextImpl.createAppContext(this, ...);
//获取Application,这个application是在应用启动的时候创建的
Application app = packageInfo.makeApplication(flase, ...);
//给service赋予上下文
service.attach(context, this, ...);
//执行Service的生命周期
service.onCreate();
mServices.put(data.token, service);
...
}
mServices是一个map:
ArrayMap
private final void sendServiceArgsLocked(ServiceRecord r, ){
while(r.pendingStarts.size() > 0){
//取出每一个pending的startItem
StartItem si = r.pendingStarts.remove(0);
...
//向应用端发起IPC调用
r.app.thread.scheduleServiceArgs(r, ...);
}
}
AMS是如何触发应用端Service的onStartCommand的
AMS调用r.app.thread.scheduleServiceArgs(r, …)后,应用端的处理:
public final void scheduleServiceArgs(IBinder token, ...) {
//封装了一个ServiceArgsData对象
ServiceArgsData s = new ServiceArgsData();
...
//丢到应用的主线程去处理
sendMessage(H.SERVICE_ARGS, s);
}
//应用端主线程的处理:
private void handleServiceArgs(ServiceArgsData data) {
//首先从mServices中把Service对象取出来。mService是一个map,其中:
//key就是AMS中的ServiceRecord的对象
//value就是应用端的Service对象
//data.token就是AMS中的ServiceRecord对象
Service s = mServices.get(data.token);
if(s != null){
...
//调用Service的onStartCommand
s.onStartCommand(data.args, data.flags, data.startId);
...
}
}
总结Service启动的流程:
AMS端:
应用端:
先创建Service对象 再赋予上下文 最后调用生命周期onCreate() 用bindService启动Service启动Service还有另一种情况:bindService的时候带上BIND_AUTO_CREATE标记
int bindServiceLocked(IApplicationThread caller, ...){
...
if((flags & Context.BIND_AUTO_CREATE) != 0){
//如果带上BIND_AUTO_CREATE标记
bringUpServiceLocked(s, ...);
}
...
}
binderService和startService的区别:
binderService不会触发应用端的onStartCommand函数
因为binderService没有把ServiceRecord加到mPendingStart队列中
回归:说说service的启动原理
service启动有几种方式?a) startService
b) bindService带BIND_AUTO_CREATE service启动过程主要流程有哪些?
a)AMS端:
1)先看Service启动了没有:如果启动了就直接发指令,让应用端执行onStartCommand()
2)如果Service没有启动,就看它所在进程启动了没有:如果已经启动,就去启动Service,等Service启动了之后再发送指令让其执行onStartCommand
3)如果进程没有启动就去启动进程,等进程启动后再启动Service
b)应用端:
1)先创建Service对象
2)再赋予上下文
3)最后调用生命周期onCreate()
a)参考下图:
作者:menghaocheng