android Service启动过程

本文源码基于Android 8.1.0。

        startService(intent);

这行代码执行后,发生了什么?

ContextWrapper.java

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

ContextImpl.java

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

这里调用了AMS在App进程中的代理对象,它实现了IActivityManager接口,而这个IActivityManager继承了IInterface。
,而这个代理对象最终会通过Binder跨进程来到ActivityManagerService中,
ActivityManagerService.java


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

这个mServices为ActiveServices对象。

ActiveService.java

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {

        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }
    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 {

        // 这里调用Service的onStartCommand()方法
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

        if (!isolated) {
            //根据进程名和uid,查询ProcessRecord
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    // 启动服务
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }
            }
        } else {
            app = r.isolatedProc;
        }

        //对于进程没有启动的情况
        if (app == null) {
            //启动service所要运行的进程
            if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {
                String msg = ""
                bringDownServiceLocked(r); // 进程启动失败
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
  • 当目标进程已存在,则直接执行realStartServiceLocked();
  • 当目标进程不存在,则先执行startProcessLocked()创建进程, 经过层层调用最后会调用到AMS.attachApplicationLocked, 然后再执行realStartServiceLocked()。
  • 对于非前台进程调用而需要启动的服务,如果已经有其他的后台服务正在启动中,那么我们可能希望延迟其启动。这是用来避免启动同时启动过多的进程(非必须的)。

目标进程不存在的情况我们先略过,来看看realStartServiceLocked():


    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);
            created = true;
        } catch (DeadObjectException e) {

        }

这里跟Activity的流程又类似了,它将会夸进程调用IApplicationThread的实现类,也就是我们ActivityThread的内部类ApplicationThread,来到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,通过发送消息来调用启动service的方法


        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {

                case CREATE_SERVICE:
                  
                    handleCreateService((CreateServiceData)msg.obj);
                    break;

            }
            Object obj = msg.obj;
        }

很简单,就是调用了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);
           
    }

到这里,先是从LoadedApk中获取ClassLoader,然后用它来创建了Service,之后再为Service创建了一个ContextImpl实例,然后又尝试去创建一个Application,当然如果已经存在,就直接返回了。
之后就是调用了Service的attach()方法,主要传入一些环境等信息。然后就调用了Service的onCreate()方法,Service正式完成启动。

Service.java

    public final void attach(
            Context context,
            ActivityThread thread, String className, IBinder token,
            Application application, Object activityManager) {
        attachBaseContext(context);
        mThread = thread;           // NOTE:  unused - remove?
        mClassName = className;
        mToken = token;
        mApplication = application;
        mActivityManager = (IActivityManager)activityManager;
        mStartCompatibility = getApplicationInfo().targetSdkVersion
                < Build.VERSION_CODES.ECLAIR;
    }

小结


可以看出,Service的启动过程比Activity的启动过程要简单很多,它的调用链没那么长。总结起来,它主要做了以下几件事:

  • Activity调用ContextImpl的startServcie方法
  • ContextImpl直接就开始调用AMS的代理对象,通过Binder向远程AMS发起启动服务的请求
  • AMS收到请求后,会先判断是否需要开启新进程,如果是本地服务,那么直接调用realStartServiceLocked()方法,然后夸进程来到ApplicationThread中,调用scheduleCreateService(),最终创建Service
  • 如果是远程服务,则会先创建新进程,然后再执行realStartServiceLocked,最终完成创建。

如果更深一步,这里面涉及到的进程交互,gityuan大神的博客可供参考。这是他博客中的图:

android Service启动过程_第1张图片
image

你可能感兴趣的:(android Service启动过程)