美文网首页
Android Service启动流程

Android Service启动流程

作者: feifei_fly | 来源:发表于2020-12-12 14:41 被阅读0次

    一、Service生命周期

    首先我们先回忆一下Service的声明周期

    image
    • 第一次调用startServie(): Service.onCreate()->Service.onStartCommand()
    • 第二次调用startService(): Service.onStartCommand()

    本周主要分析上面两步操作,Service的启动行为。

    二、Service启动分析

    image

    阶段一:app进程startService(),向SystemServer进程发送启动Service的请求

    首先明确一点,启动Service、启动Activity、发送广播,这些都是Context上下文的本职工作。
    在Applciation、Activity或者Service中都可以调用startService(),最终会调用到ContextImpl.startService()

    • ContextImpl.StartService
    • ContextImpl.startServiceCommon
    • ActivityManager.getService().startService()

    阶段二:SystemService进程 处理启动Service请求

    在ActivityManagerService中,启动service的操作 是委托给ActiveServices执行的。

    • ActivityManagerService.startService()
    • ActiveServices.startServiceLocked()

    startServiceLocked方法中会解析要启动的Service,创建对应的ServiceRecord实例,最终调用自身bringUpServiceLocked方法。

    ## ActiveServices.java
    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
    int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
    throws TransactionTooLargeException {
    
        //(1)解析、创建响应的ServiceRecord
      ServiceLookupResult res =retrieveServiceLocked(service, resolvedType, callingPackage,
                        callingPid, callingUid, userId, true, callerFg, false, false);
    
     ServiceRecord r = res.record;  
    
     //(2)调用内部方法
      ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);       
    
    }
    
    • ActiveServices.startServiceInnerLocked()
    • ActiveServices.bringUpServiceLocked()

    bringUpServiceLocked是处理Service启动逻辑的核心方法。

     private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                boolean whileRestarting, boolean permissionsReviewRequired)
                throws TransactionTooLargeException {
    
    
    //注释一:如果Service已经创建,则直接调用sendServiceArgsLocked(),最终会触发Service.onStartCommand()方法调用
     if (r.app != null && r.app.thread != null) {
                sendServiceArgsLocked(r, execInFg, false);
                return null;
            }
            
     final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    
      if (!isolated) {  
         
         //注释二:非独立进程,则直接启动Service:onCreate(),onStartCommad()方法
          realStartServiceLocked(r, app, execInFg);
    
      }else {
            //注释三: 如果Service要运行独立进程,且进程不存在,则创建新进程.      
            if (app == null && !permissionsReviewRequired) {
                    if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                            hostingType, r.name, false, isolated, false)) == null) {
                        String msg = "Unable to launch app "
                                + r.appInfo.packageName + "/"
                                + r.appInfo.uid + " for service "
                                + r.intent.getIntent() + ": process is bad";
                        Slog.w(TAG, msg);
                        bringDownServiceLocked(r);
                        return msg;
                    }
                    if (isolated) {
                        r.isolatedProc = app;
                    }
            }
               
      }
    }
    
    • 注释一:如果Service已经创建,则直接调用sendServiceArgsLocked(),最终调用Service.onStartCommand()方法。对应第二次调用StartService方法的场景,此场景Service仅会回调onStartCommand()回调
    • 注释二:如果Service不要求运行在新的进程,则调用realStartServiceLocked()方法,该方法 会触发Service.onCreate()和onStartCommand()方法
    • 注释三: 如果Service要运行独立进程,且进程不存在,则创建新进程.

    阶段三:ActivityMangaerService 与 ActivityThread IPC互动过程。

    下面我们一起来看一下ActiveServices是 如何创建,并启动Service的。

    核心方法在realStartServiceLocked()

    private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
    
        //(1)向ApplicationThread发送消息,创建Service
       app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
    
        //(2)向Service发送参数
        sendServiceArgsLocked(r, execInFg, true);
    }
    
    

    1、scheduleCreateService

    利用ApplicationThread 向app进程发送IPC消息

    • ApplicationThread.scheduleCreateService()
    • ApplicationThread发送H.CREATE_SERVICE消息
    • ActivityThread.handleCreateService()
    private void handleCreateService(CreateServiceData data) {
    
        //(1)创建Service
       service = packageInfo.getAppFactory()
                .instantiateService(cl, data.info.name, data.intent);
        //(2)创建ContextImpl
       ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
       //(3)调用Service.attah()
      service.attach(context, this, data.info.name, data.token, app,
            ActivityManager.getService());
       //(4)调用Service.onCreate()
       service.onCreate();
     }
    

    handleCreateService()中完成了以下操作:

    • 利用LoaedApk创建了Service实例,
    • 创建ContextImpl()实例
    • 调用Service.attach()完成ContextImpl的绑定
    • 调用Service.onCreate()方法

    2、 sendServiceArgsLocked 启动Service的参数处理

    ActiveServices.sendServiceArgsLocked 主要做的操作就是,通过ApplicationThread发送scheduleServiceArgs的IPC消息

    private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,boolean oomAdjusted) throws TransactionTooLargeException {
          r.app.thread.scheduleServiceArgs(r, slice);
    }
    
    • ApplicationThread.scheduleServiceArgs()
     public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
                List<ServiceStartArgs> list = args.getList();
    
                for (int i = 0; i < list.size(); i++) {
                    ServiceStartArgs ssa = list.get(i);
                    ServiceArgsData s = new ServiceArgsData();
                    s.token = token;
                    s.taskRemoved = ssa.taskRemoved;
                    s.startId = ssa.startId;
                    s.flags = ssa.flags;
                    s.args = ssa.args;
    
                    sendMessage(H.SERVICE_ARGS, s);
                }
            }
    
    
    • 发送H.SERVICE_ARGS 消息
    • ActivityThread.handleServiceArgs(),调用Service.onStartCommand()
    
      private void handleServiceArgs(ServiceArgsData data) {
         Service s = mServices.get(data.token);
          if (!data.taskRemoved) {
                res = s.onStartCommand(data.args, data.flags, data.startId);
            } else {
                s.onTaskRemoved(data.args);
                res = Service.START_TASK_REMOVED_COMPLETE;
            }
      }  
    

    三、参考文章

    https://www.jianshu.com/p/cc25fbb5c0b3
    https://www.jianshu.com/p/e65cfcbdd11e

    相关文章

      网友评论

          本文标题:Android Service启动流程

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