【Android源码】Service的启动过程

作者: 指间沙似流年 | 来源:发表于2017-07-03 10:11 被阅读104次

    通常情况下,我们启动或者绑定一个Service是通过如下代码:

    Intent intent = new Intent(this, TestService.class);
    startService(intent);
    bindService(intent, mServiceConneftion, BIND_AUTO_CREATE);
    

    Service的启动是从ContextWrapper的startService开始的:

    @Override
    public ComponentName startService(Intent service) {
       return mBase.startService(service);
    }
    

    上面代码中的mBase的类型是Context,而从Activity的启动流程我们知道了,ContextImpl对象就是Context的具体实现,Activity被创建的时候会通过attach方法将ContextImpl对象关联起来,而这个ContextImpl就是mBase。

    // ContextImpl.java
    @Override
    public ComponentName startService(Intent service) {
       warnIfCallingFromSystemProcess();
       return startServiceCommon(service, mUser);
    }
    
    private ComponentName startServiceCommon(Intent service, UserHandle user) {
       try {
           validateServiceIntent(service);
           service.prepareToLeaveProcess(this);
           ComponentName cn = ActivityManagerNative.getDefault().startService(
               mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                           getContentResolver()), getOpPackageName(), user.getIdentifier());
           if (cn != null) {
               if (cn.getPackageName().equals("!")) {
                   throw new SecurityException(
                           "Not allowed to start service " + service
                           + " without permission " + cn.getClassName());
               } else if (cn.getPackageName().equals("!!")) {
                   throw new SecurityException(
                           "Unable to start service " + service
                           + ": " + cn.getClassName());
               }
           }
           return cn;
       } catch (RemoteException e) {
           throw e.rethrowFromSystemServer();
       }
    }
    

    startService又会调用startServiceCommon,而在startServiceCommon中,又会通过ActivityManagerNative.getDefault().startService来启动一个服务。
    ActivityManagerNative其实就是AMS:

    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
           String resolvedType, String callingPackage, int userId)
           throws TransactionTooLargeException {
       enforceNotIsolatedCaller("startService");
       // Refuse possible leaked file descriptors
       if (service != null && service.hasFileDescriptors() == true) {
           throw new IllegalArgumentException("File descriptors passed in Intent");
       }
    
       if (callingPackage == null) {
           throw new IllegalArgumentException("callingPackage cannot be null");
       }
    
       if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
               "startService: " + service + " type=" + resolvedType);
       synchronized(this) {
           final int callingPid = Binder.getCallingPid();
           final int callingUid = Binder.getCallingUid();
           final long origId = Binder.clearCallingIdentity();
           ComponentName res = mServices.startServiceLocked(caller, service,
                   resolvedType, callingPid, callingUid, callingPackage, userId);
           Binder.restoreCallingIdentity(origId);
           return res;
       }
    }
    

    其中通过mServices.startServiceLocked来完成后续的启动过程,mServicesActiveServices,是一个辅助AMS来管理Service的类,包括启动、绑定、停止等操作。

    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;
    }
    
    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
           boolean whileRestarting, boolean permissionsReviewRequired)
           throws TransactionTooLargeException {
        realStartServiceLocked(r, app, execInFg);       
    }
    

    通过不断的调用最终调用到了realStartServiceLocked(r, app, execInFg)方法,通过名称我们可以猜测这个就是最终创建Service的方法:

    app.thread.scheduleCreateService(r, r.serviceInfo,
                        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                        app.repProcState);
    

    通过app.threadscheduleCreateService来创建Service对象并调用onCreate。

    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);
    }
    
     case CREATE_SERVICE:
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
         handleCreateService((CreateServiceData)msg.obj);
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         break;
    

    这个和Activity的处理几乎一样,都是通过H这个Handler对象来发送消息,并处理的创建过程的:

    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 = (Service) cl.loadClass(data.info.name).newInstance();
       } catch (Exception e) {
           if (!mInstrumentation.onException(service, e)) {
               throw new RuntimeException(
                   "Unable to instantiate service " + data.info.name
                   + ": " + e.toString(), e);
           }
       }
    
       try {
           if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
    
           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,
                   ActivityManagerNative.getDefault());
           service.onCreate();
           mServices.put(data.token, service);
           try {
               ActivityManagerNative.getDefault().serviceDoneExecuting(
                       data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
           } catch (RemoteException e) {
               throw e.rethrowFromSystemServer();
           }
       } catch (Exception e) {
           if (!mInstrumentation.onException(service, e)) {
               throw new RuntimeException(
                   "Unable to create service " + data.info.name
                   + ": " + e.toString(), e);
           }
       }
    }
    

    这个方法主要做了这样几件事:

    1. 通过类加载器创建Service实例。
    2. 创建Application对象,并通过service的attach方法关联Application。
    3. 调用service的onCreate方法将Service对象存到ActivityThread的管理Service的列表中。

    我们在回到realStartServiceLocked中,在scheduleCreateService之后又调用了sendServiceArgsLocked(r, execInFg, true)方法。
    scheduleCreateService方法是创建Service对象,并调用onCreate方法。
    sendServiceArgsLocked方法则是调用了onStartCommand方法。

    r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
    
    public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
      int flags ,Intent args) {
      ServiceArgsData s = new ServiceArgsData();
      s.token = token;
      s.taskRemoved = taskRemoved;
      s.startId = startId;
      s.flags = flags;
      s.args = args;
    
      sendMessage(H.SERVICE_ARGS, s);
    }
    
     case SERVICE_ARGS:
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
         handleServiceArgs((ServiceArgsData)msg.obj);
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         break;
         
    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 {
                   ActivityManagerNative.getDefault().serviceDoneExecuting(
                           data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
               } catch (RemoteException e) {
                   throw e.rethrowFromSystemServer();
               }
               ensureJitEnabled();
           } catch (Exception e) {
               if (!mInstrumentation.onException(s, e)) {
                   throw new RuntimeException(
                           "Unable to start service " + s
                           + " with " + data.args + ": " + e.toString(), e);
               }
           }
       }
    }
    

    这个时候调用了res = s.onStartCommand(data.args, data.flags, data.startId)方法,也就是说Service的启动过程已经分析完了。

    后篇: Service的绑定过程

    相关文章

      网友评论

        本文标题:【Android源码】Service的启动过程

        本文链接:https://www.haomeiwen.com/subject/uffocxtx.html