[Android] to talk about topics related to application startup -5.1 principle of service

Study content:

  • What are the different ways to start service?
  • service during startup key processes What?
  • service which involves participants start the communication process like?

Service starts principles

Start with 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;
}

The AMS process:

ComponentName startService(IApplicationThread caller, Intent service, ...){
  ComponentName res = mServices.startServiceLocked(caller, service, ...);
  return res;
}

The intent query service Record Object:
each application in the AMS Service terminal corresponds to a target 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);
  }
  ...
}

A flow chart of the process started:
Here Insert Picture Description

  • AMS initiated the request to start the process through the socket Zygote
  • Zygote process will start after the receipt of the request
  • Binder application process initiated calls attachApplication to AMS, his own binder object is registered to AMS (After registering for the AMS for this application even if the ready)
  • Sign up through the application process applicationThread initiate bindApplication calls to the application side, the main application initialization application (this step after it's happened AMS can handle Pending the components)

AMS processing functions attachApplication of:

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, ...);
}

How to deal with AMS application side is made up of CreateServicd request:

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<IBinder, Service>
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, ...);
  }
}

How AMS is triggered onStartCommand the application side of the Service

After the AMS calls r.app.thread.scheduleServiceArgs (r, ...), the application side of the deal:

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);
    ...
  }
}

Summary Service startup process:

Here Insert Picture Description
AMS end:

  • Look at the Service initiated no: If you start to send commands directly, so the application side perform onStartCommand ()
  • If the Service does not start, to see it in the process did not start: If you have already started, go to Start Service, and other onStartCommand allowed to perform the re-start after the Service to send commands
  • If the process does not start then went to the boot process, such as process starts start Service

Application end:

  • Create Service objects
  • And then give context
  • The last call life cycle onCreate ()

Service starts with bindService

Start Service There is another situation: bindService time to bring BIND_AUTO_CREATE mark

int bindServiceLocked(IApplicationThread caller, ...){
  ...
  if((flags & Context.BIND_AUTO_CREATE) != 0){
    //如果带上BIND_AUTO_CREATE标记
    bringUpServiceLocked(s, ...);
  }
  ...
}

binderService and startService difference:

  • binderService onStartCommand function does not trigger the application side
  • Because no binderService the queue ServiceRecord added mPendingStart

Start to talk about the principle of service: the return

  • There are several ways to start the service?
    A) the startService
    B) with BIND_AUTO_CREATE bindService
  • The main service startup process What?
    a) AMS end:
    1) look at the Service does not start up: If you start to send commands directly, so the application side perform onStartCommand ()
    2) If the Service does not start, to see it in the process did not start: If you have already started, you Service to start, after the start of the Service, etc. and then send commands allowed to perform onStartCommand
    then 3) If the process does not start go to start the process, such as process starts start Service

b) the application side:
1) create Service objects
2) and then give context
3) finally calls lifecycle onCreate ()

  • service startup process which the participants, communication process like?
    a) with reference to the following figure:Here Insert Picture Description
Published 119 original articles · won praise 28 · Views 100,000 +

Guess you like

Origin blog.csdn.net/menghaocheng/article/details/104595958