Android Service启动流程分析


之前写过App和Activity的启动流程分析:

现在梳理下Service的启动流程吧

基于Android 10的源码分析

ContextWrapper.startService()

Context的实现是ContextImpl,因此到ContextImpl中查看:

    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            // 关键, 利用ActivityManagerService启动Service
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

还是调用的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 {
                // 这里的mServices是ActiveServices
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

然后就到了ActiveServices中,这个类其实在之前的启动流程分析文章中也有提到过:

    // startService 和bindService两种方式其实最终都会走到这里
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        r.setProcess(app);
        boolean created = false;
        try {
            //ApplicationThread,关键点
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.getReportedProcState());
            r.postNotification();
            created = true;
        } 

        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(app, null, true);

        if (newService && created) {
            app.addBoundClientUidsOfNewService(r);
        }

        // 这里也很关键
        sendServiceArgsLocked(r, execInFg, true);
    }

这期间调用链其实很长,这里直接走到最后一步.

ActivityThread.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;
            // handler机制
            sendMessage(H.CREATE_SERVICE, s);
        }

Handler收到消息之后:

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

加载Service类,并执行onCreate回调

    private void handleCreateService(CreateServiceData data) {
        // 获取APP信息
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        // 使用ClassLoader加载并实例化Service类
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);


        try {
            // 创建Context
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            // 创建Application
            Application app = packageInfo.makeApplication(false, mInstrumentation);

            // 执行service的attach方法
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService()); 
            ///调用service的onCreate回调
            service.onCreate();
            mServices.put(data.token, service);
            try {
                // 通知AMS服务
                // SERVICE_DONE_EXECUTING_ANON表示异步执行
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

可以看到,Service的启动过程其实和Activity的启动过程大同小异,都是使用ClassLoader加载的.

还有最后一句,通知ActivityManagerService,看下这部分干了什么:

    public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
        synchronized(this) {
            mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
        }
    }

    // SERVICE_DONE_EXECUTING_ANON,0,0
    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
        boolean inDestroying = mDestroyingServices.contains(r);
        final long origId = Binder.clearCallingIdentity();
        //主要是一些超时逻辑
        serviceDoneExecutingLocked(r, inDestroying, inDestroying);
        Binder.restoreCallingIdentity(origId);
    } 

可以看到这一步其实没什么.

现在回到onCreate回调之后的处理逻辑:

    private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        ArrayList<ServiceStartArgs> args = new ArrayList<>();
        // 关键点
        r.app.thread.scheduleServiceArgs(r, slice);
    }

这个会执行到ActivityThread的ApplicationThread中:

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

Handelr收到消息之后有:

                case SERVICE_ARGS:
                    handleServiceArgs((ServiceArgsData)msg.obj);
                    break;

这里其实会执行Service 的onStartCommand()回调:

Service.onStartCommand()

    private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                int res;
                if (!data.taskRemoved) {
                    // 调用Service的onStartCommand方法
                    res = s.onStartCommand(data.args, data.flags, data.startId);
                } else {
                    s.onTaskRemoved(data.args);
                    res = Service.START_TASK_REMOVED_COMPLETE;
                }
                QueuedWork.waitToFinish();
                                // 通知AMS service启动
                try {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
        }
    }

执行完Service的onStartCommand()方法之后,会通知AMS:

    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
        boolean inDestroying = mDestroyingServices.contains(r);
        if (r != null) {
            if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
                // 执行这个分支
                r.callStart = true;
                switch (res) {
                    case Service.START_STICKY_COMPATIBILITY:
                    case Service.START_STICKY: {
                        // We are done with the associated start arguments.
                        r.findDeliveredStart(startId, false, true);
                        // Don't stop if killed.
                        r.stopIfKilled = false;
                        break;
                    }
                    case Service.START_NOT_STICKY: {
                        // We are done with the associated start arguments.
                        r.findDeliveredStart(startId, false, true);
                        if (r.getLastStartId() == startId) {
                            // There is no more work, and this service
                            // doesn't want to hang around if killed.
                            r.stopIfKilled = true;
                        }
                        break;
                    }
                    case Service.START_REDELIVER_INTENT: {
                        // We'll keep this item until they explicitly
                        // call stop for it, but keep track of the fact
                        // that it was delivered.
                        ServiceRecord.StartItem si = r.findDeliveredStart(startId, false, false);
                        if (si != null) {
                            si.deliveryCount = 0;
                            si.doneExecutingCount++;
                            // Don't stop if killed.
                            r.stopIfKilled = true;
                        }
                        break;
                    }
                    case Service.START_TASK_REMOVED_COMPLETE: {
                        // Special processing for onTaskRemoved().  Don't
                        // impact normal onStartCommand() processing.
                        r.findDeliveredStart(startId, true, true);
                        break;
                    }
                    default:
                        throw new IllegalArgumentException(
                                "Unknown service start result: " + res);
                }
                if (res == Service.START_STICKY_COMPATIBILITY) {
                    r.callStart = false;
                }
            } 
        }
    }

这里其实就是处理不同类型的Service,比如Sticky Service的启动逻辑,这里不仔细说了.

总结

  1. Service的启动流程和Activity的启动流程大同小异
  2. ActivityThread和AMS起到了关键性的作用
  3. 不同类型Service在AMS中有处理逻辑

文章作者: 姜康
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 姜康 !
评论
 上一篇
用SDL写个Hello World 用SDL写个Hello World
const int WIDTH = 600; const int HEIGHT = 600; void SDLExample() { if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
2020-09-12
下一篇 
Activity启动流程分析 Activity启动流程分析
在App启动流程分析中已经分析过大部分的流程了,但是对于Activity的启动流程并没有详细的说明,这里讲一下. 在分析源码之前,先想一下大概有哪些疑问: Activity是如何加载的? Activity为什么必须在Manifest文件中
2020-08-23
  目录