美文网首页
源码分析:service启动流程

源码分析:service启动流程

作者: 一线游骑兵 | 来源:发表于2018-09-20 12:12 被阅读6次

    目的:梳理一下service的启动流程

    从context.startService入口,其实现类为ContextImpl

    ContextImpl.startService:

        @Override
        public ComponentName startService(Intent service) {
            warnIfCallingFromSystemProcess();
            return startServiceCommon(service, false, mUser);
        }
    
        private ComponentName startServiceCommon(Intent service, boolean requireForeground,
                UserHandle user) {
            try {
                validateServiceIntent(service);
                service.prepareToLeaveProcess(this);
                ComponentName cn = ActivityManager.getService().startService(
                    mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                                getContentResolver()), requireForeground,
                                getOpPackageName(), user.getIdentifier());
                ...
                return cn;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    

    对比Activity启动流程发现,这里直接调动了AMS的方法,进入ActivityManagerService的该方法中:
    ActivityManagerService.startService:

      @Override
        public ComponentName startService(IApplicationThread caller, Intent service,
                String resolvedType, boolean requireForeground, String callingPackage, int userId)
                throws TransactionTooLargeException {
            ...
            synchronized(this) {
                final int callingPid = Binder.getCallingPid();
                final int callingUid = Binder.getCallingUid();
                final long origId = Binder.clearCallingIdentity();
                ComponentName res;
                try {
                    res = mServices.startServiceLocked(caller, service,
                            resolvedType, callingPid, callingUid,
                            requireForeground, callingPackage, userId);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
                return res;
            }
        }
    

    发现调用了ActiveServicesstartServiceLocked

        ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
                int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
                throws TransactionTooLargeException {
            //一系列的app进程校验,权限校验,后台进程的延时处理等
    
            ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
            return cmp;
        }
    

    同样,进入inner的相关方法:

       ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
                boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
            ServiceState stracker = r.getTracker();
            if (stracker != null) {
                stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
            }
            r.callStart = false;
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startRunningLocked();
            }
            String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
            ...
    
            return r.name;
        }
    

    关键代码应该在bringUpServiceLocked方法中:

        private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                boolean whileRestarting, boolean permissionsReviewRequired)
                throws TransactionTooLargeException {
            //对一些状态进行了判断处理
          
            //延时的处理,服务独立进程的处理,权限的处理等
    
            if (!isolated) {
                app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
               
                if (app != null && app.thread != null) {
                        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,
                hostingType, r.name, false, isolated, false)) == null) {
            bringDownServiceLocked(r);
            return msg;
            }
        }
            ...
    
            return null;
        }
    

    如果app所在进程不为空,则进入realStartServiceLocked开启Service。否则通过mAm.startProcessLocked创建service所在进程。
    点击进入realStartServiceLocked:

      private final void realStartServiceLocked(ServiceRecord r,
                ProcessRecord app, boolean execInFg) throws RemoteException {
         
            boolean created = false;
            try {
                ...
                app.thread.scheduleCreateService(r, r.serviceInfo,
                        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                        app.repProcState);
                r.postNotification();
                created = true;
            } catch (DeadObjectException e) {
                mAm.appDiedLocked(app);
                throw e;
            } finally {
                if (!created) {
    
                    // Retry.
                    if (!inDestroying) {
                        scheduleServiceRestartLocked(r, false);
                    }
                }
            }
              //...
             requestServiceBindingsLocked(r, execInFg);
        }
    

    可以发现,此时方法已经通过app.thread.scheduleCreateService调回到了app进程中的方法。
    进入ApplicationThread类中的scheduleCreateService方法:

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

    在主线程中的looper中发送了一个消息,最终调用了handleCreateService方法:

     private void handleCreateService(CreateServiceData data) {
    
            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 {
    
                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,
                        ActivityManager.getService());
                service.onCreate();
                mServices.put(data.token, service);
                try {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } catch (Exception e) {
            }
        }
    

    在该方法中,首先通过反射创建了一个Service,然后调用了attach方法,接着回调了service.onCreate();方法,然后通知了AMS创建成功。
    之后在realStartServiceLocked方法中通知app进程创建service之后又调用了下边一行代码:

            requestServiceBindingsLocked(r, execInFg);
    

    该方法最终调用了

        private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
                boolean execInFg, boolean rebind) throws TransactionTooLargeException {
    
            if ((!i.requested || rebind) && i.apps.size() > 0) {
                try {
                    r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                            r.app.repProcState);
                } catch (TransactionTooLargeException e) {}
            }
            return true;
        }
    
    

    发现又通过Binder回调掉app进程中的scheduleBindService方法。

        private void handleBindService(BindServiceData data) {
            Service s = mServices.get(data.token);
            if (s != null) {
                try {
                    data.intent.setExtrasClassLoader(s.getClassLoader());
                    try {
                        if (!data.rebind) {
                            IBinder binder = s.onBind(data.intent);
                            ActivityManager.getService().publishService(
                                    data.token, data.intent, binder);
                        } else {
                            s.onRebind(data.intent);
                            ActivityManager.getService().serviceDoneExecuting(
                                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                        }
                      
                    } catch (RemoteException ex) {
                        throw ex.rethrowFromSystemServer();
                    }
                } catch (Exception e) {
                }
            }
        }
    

    该方法最终回调了service的onBind方法。
    此时,无论是通过startService还是bindService都已经启动了servcie。

    相关文章

      网友评论

          本文标题:源码分析:service启动流程

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