【源码】startService流程

startService笔记

ContextImpl

1、startService

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

2、startServiceCommon

Android 5.0开始不允许隐式启动Service

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            //如果SDK 版本大于LOLLIPOP 的,要求service 不能隐式启动。
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            //远程调用AMS服务
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            // ...
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

AMS

1、startService

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

ActiveService

1、startServiceLocked

    ComponentName startServiceLocked(...)
            throws TransactionTooLargeException {
        //调用同名方法startServiceLocked
        return startServiceLocked(...);
    }

2、startServiceLocked

    ComponentName startServiceLocked(...)
            throws TransactionTooLargeException {
        //主要做了一些参数过滤

        //调用startServiceInnerLocked
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }

3、startServiceInnerLocked

    ComponentName startServiceInnerLocked(...) throws TransactionTooLargeException {
        //调用bringUpServiceLocked
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        

        return r.name;
    }

4、bringUpServiceLocked

这个方法主要有三个分支

  • 1、Service已经create过了,再次调用只会触发sendServiceArgsLocked从而回调onStartCommand
  • 2、Service没有create过,但是目标进程存在,则创建进程后再创建Service
  • 3、Service的目标进程不存在,这里就会先创建进程、创建Application、创建Service,因为步骤和Activity的启动流程相差无几,所以这里不再赘述本分支
    //判断是否有ProcessRecord,没有的话则通过AMS创建进程,有的话调
    //用
    private String bringUpServiceLocked(...){
    	//分支1
        //该service 已经create,再次调用startService() 函数的时
        //候,会直接调用sendServiceArgsLocked()
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

        //...
		
		//分支2
        //如果service 的ProcessRecord 已经创建了,会直接调用
        //realStartServiceLocked(),进入start service 的最终流程
        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            

            if (app != null && app.thread != null) {
                try {
                    //调用realStartServiceLocked
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } 
            }
        }
		
		//分支3
        //如果service 还没有create,会调用AMS 中startProcessLocked() 创建
        if (app == null && !permissionsReviewRequired) {
            //创建进程、进而创建Application
            if ((app=mAm.startProcessLocked(...)) == null) {
                //...
            }
            
        }

        return null;
    }

分支1

1、sendServiceArgsLocked

Service已经create的情况下,会调用该方法,这里主要做了两件事:

  • 1、发送ANR消息
  • 2、调用ActivityThreadscheduleServiceArgs去触发onStartCommand

    /**
    1、每次startService,都会对应一次onStartCommand,就算Service已经onCreate成功。
    2、Service的回调函数都是在主线程,
    
    **/
    private final void sendServiceArgsLocked(...){

        //这里处理超时
        bumpServiceExecutingLocked(r, execInFg, "start");

        //1、调用ActivityThread的scheduleServiceArgs
        //2、ActivityThread通过Handler发送消息调用handleServiceArgs
        //重要!!!这也就是为什么每次startService都会回调一次onStartCommand
        try {
            r.app.thread.scheduleServiceArgs(r, slice);
        } 
    }


ActivityThread

2、handleServiceArgs

r.app.thread.scheduleServiceArgs主要通过Handler触发handleServiceArgs
在这里面做了几件主要的事情:

  • 1、回调onStartCommand
  • 2、调用AMS方法serviceDoneExecuting,在方法里面removeANR消息。值得留意的是serviceDoneExecuting是一个oneway方法,说明它不会阻塞客户端
    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 {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                }
            } catch (Exception e) {
                
            }
        }
    }


分支2

ActiveService

1、realStartServiceLocked

Service没有创建过的情况下,会做以下几件事情:

  • 1、处理ANR
  • 2、app.thread.scheduleCreateService通过Handler触发
  • 3、因为不满足条件,所以进入requestServiceBindingsLocked后不会调用onBind
  • 4、调用sendServiceArgsLocked回调onStartCommand,因为这部分代码分支1已经贴出,这里就不再贴了
    private final void realStartServiceLocked(...) {
        
        //这里创建了一个ServiceRecord
        r.setProcess(app);
        final boolean newService = app.services.add(r);
        //处理超时
        bumpServiceExecutingLocked(r, execInFg, "create");

        //...

        boolean created = false;
        try {
            //1、继续通过ActivityThread发送消息,去回调OnCreate
            app.thread.scheduleCreateService(...);
            
        } catch (DeadObjectException e) {}

        //这一行代码是bindService的流程,但是因为r.bindingSize < 0,所以并不会
        //真正执行onBind
        requestServiceBindingsLocked(r, execInFg);
        updateServiceClientActivitiesLocked(app, null, true);


        //回调onStartCommand
        sendServiceArgsLocked(r, execInFg, true);

    }

ActivityThread

1、handleCreateService

在这里面主要做了几件事:

  • 1、创建Service
  • 2、创建ServiceContextImpl
  • 3、回调ServiceattachonCreate
  • 4、告诉AMS服务已经创建完毕,remove ANR消息

接着还会调用realStartServiceLocked里面的sendServiceArgsLocked去回调onStartCommand

    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 = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
        }

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

分支3

创建进程和Application后再创建Service,这里不再赘述


总结

整体流程

  • 1、通过ContextImpl调用到AMS的启动方法
  • 2、AMS将逻辑交给ActiveService处理
  • 3、ActiveServicebringUpServiceLocked分三种情况
    • (1)Service已经Create过:回调ServiceonStartCommand
    • (2)Service没有Create过,但目标进程存在:回调ServiceonCreateonStartCommand
    • (3)Service的目标进程不存在:创建进程和Application后再创建Service,接着回调ServiceonCreateonStartCommand

时序图

欠着先,打扰了…


流程图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值