四大组件之Service(一)-Service启动过程

Service启动过程与Activity类似,了解了Activity启动之后来看Service就容易了,那么还是来简单过一下流程,先看一张整体流程图:

四大组件之Service(一)-Service启动过程_第1张图片

应用层startService 最终通过Binder IPC 到AMS:

四大组件之Service(一)-Service启动过程_第2张图片

Context关系以后再讲,这里其实我们都知道Context是个抽象类,真正干活的是ContextImpl. 由它执行真正的startService操作:

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

这是典型的binder ipc过程了,话不多说。

四大组件之Service(一)-Service启动过程_第3张图片
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
        ...
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
        ...
        return res;
    }
}

执行startServiceLocked:

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
           int callingPid, int callingUid, String callingPackage, final int userId)
           throws TransactionTooLargeException {
     ...
       return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
   }
  ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
           boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    ...
       String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    ...
       return r.name;
   }

startServiceLocked 和startServiceInnerLocked 对应于Activity中的startActivityMayWait和startActivity的过程,无非也就是一些检验和初始化的工作。而startServiceInnerLocked方法中又调用了bringUpServiceLocked方法.

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
...
  final String procName = r.processName;
  ProcessRecord app;
  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;
                } 
         ...
if (app == null && !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {
              ...
            }
          ...
        }
...     

}

该方法可以对比于Activity启动的startSpecificActivityLocked,也是一个分叉路,如果进程存在则调用realStartServiceLocked去schedule Service应用层的启动,如果不存在,则socket通知Zygote去fork进程,然后再回来schedule Service。Zygote去fork进程部分与Activity启动部分并无太大差别,那么直接来看startSpecificActivityLocked:

private final void realStartServiceLocked(ServiceRecord r,
       ProcessRecord app, boolean execInFg) throws RemoteException {
  ...
   try {
      ...
       app.thread.scheduleCreateService(r, r.serviceInfo,
               mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
               app.repProcState);
       r.postNotification();
       created = true;
   } catch (DeadObjectException e) {
     ...
   }
   ...
}

app.thread是IApplicationThread类型的,它的实现是ActivityThread的内部类ApplicationThread。

frameworks/base/core/java/android/app/ActivityThread.java
public final void scheduleCreateService(IBinder token,
        ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
    updateProcessState(processState, false);
    CreateServiceData s = new CreateServiceData();
    s.token = token;
    s.info = info;
    s.compatInfo = compatInfo;
    sendMessage(H.CREATE_SERVICE, s);
}

到了ActivityThread的地界,那就是靠消息驱动运转的世界了,由H发送CREATE_SERVICE的消息,然后在handleMessage对应的case中执行的是handleCreateService

private void handleCreateService(CreateServiceData data) {
      unscheduleGcIdler();
      LoadedApk packageInfo = getPackageInfoNoCheck(
              data.info.applicationInfo, data.compatInfo);
      Service service = null;
      try {
          java.lang.ClassLoader cl = packageInfo.getClassLoader();
          service = (Service) cl.loadClass(data.info.name).newInstance();
      } catch (Exception e) {
         ...
          }
      }
      try {
          if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
          ContextImpl context = ContextImpl.createAppContext(this, packageInfo);//4
          context.setOuterContext(service);
          Application app = packageInfo.makeApplication(false, mInstrumentation);
          service.attach(context, this, data.info.name, data.token, app,
                  ActivityManagerNative.getDefault());//5
          service.onCreate();//6
          mServices.put(data.token, service);//7
       ...
      } catch (Exception e) {
          ...
      }
  }

这里主要干两件事:

  • 将service load到内存

  • 通过Service的attach方法来初始化Service,然后走Service的onCreate方法,这样Service就启动了。

好了今天就简单地总结了下Service的启动过程,下篇接着看看Service的绑定过程。

参考:
http://gityuan.com/2016/03/06/start-service/
http://liuwangshu.cn/framework/component/2-service-start.html

你可能感兴趣的:(四大组件之Service(一)-Service启动过程)