欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android Service的启动流程源码分析

程序员文章站 2022-10-31 21:11:50
一,写在前面 android service的启动流程分析,在android中服务有两种状态,一种是启动服务,一种是绑定服务,它们有着不同的生命周期。启动服务的生命周期:oncr...

一,写在前面

android service的启动流程分析,在android中服务有两种状态,一种是启动服务,一种是绑定服务,它们有着不同的生命周期。启动服务的生命周期:oncreate,onstart,ondestroy;绑定服务的生命周期:oncreate,onbind,onunbind,ondestroy。至于服务具体如何使用,本篇将不做介绍。主要介绍从源码角度,解析启动服务过程。需要注意的是,本篇文章之前建议先了解activity的启动流程。

二,进入主题

通常需要在activity中启动一个服务,用于在后台执行一些计算的操作。这时,会调用startservice(intent service)方法,其实这个方法的具体实现在activity的父类contextwrapper类中,类contextwrapper是context的子类。好了,查看源码开始分析吧~

查看contextwrapper$startservice源码:

    @override
    public componentname startservice(intent service) {
        return mbase.startservice(service);
    }
第3行,字段mbase是context类型,但context是一个抽象类,事实上mbase变量是一个contextimpl对象。给mbase变量设置值是在activity$attach方法被调用时完成,具体分析见文章android activity的启动流程源码解析,这里不再重复阐述。

 

查看contextimpl$startservice方法源码:

    @override
    public componentname startservice(intent service) {
        warnifcallingfromsystemprocess();
        return startservicecommon(service, false, muser);
    }

//继续查看

    private componentname startservicecommon(intent service, boolean requireforeground,
            userhandle user) {
       //...code

	componentname cn = activitymanager.getservice().startservice(
                mmainthread.getapplicationthread(), service, service.resolvetypeifneeded(
                            getcontentresolver()), requireforeground,
                            getoppackagename(), user.getidentifier());
	
	//...code
    }
第13行,activitymanager.getservice()返回的是一个iactivitymanager的一个代理对象,利用aidl技术完成进程间通信,需要找到那个extendsiactivitymanager.stub的实现类,它就是activitymanagerservice。iactivitymanager的代理对象调用startservice方法,会向服务activitymanagerservice发送一个请求,基于binder机制,会调用activitymanagerservice$startservice方法。详细的代码流程分析见文章android activity的启动流程源码解析,这里不再重复阐述。

 

查看activitymanagerservice$startservice方法源码:

@override
    public componentname startservice(iapplicationthread caller, intent service,
            string resolvedtype, boolean requireforeground, string callingpackage, int userid)
            throws transactiontoolargeexception {
	
	//...code

        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;
        }
    }
第14行,变量mservices是activeservices类型的对象。于是,启动服务的工作交给了activeservices来处理。

 

查看activeservices源码如下:

    componentname startservicelocked(iapplicationthread caller, intent service, string resolvedtype,
            int callingpid, int callinguid, boolean fgrequired, string callingpackage, final int userid)
            throws transactiontoolargeexception {
	    
	    //...code

	    servicelookupresult res =
            retrieveservicelocked(service, resolvedtype, callingpackage,
                    callingpid, callinguid, userid, true, callerfg, false);

	    //...code

	    servicerecord r = res.record;

	    //...code

	    r.lastactivity = systemclock.uptimemillis();
            r.startrequested = true;
            r.delayedstop = false;
            r.fgrequired = fgrequired;
            r.pendingstarts.add(new servicerecord.startitem(r, false, r.makenextstartid(),
                service, neededgrants, callinguid));
	    
	    //...code

	    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);
	    
	    //...
    } 
    
    //继续查看

    private string bringupservicelocked(servicerecord r, int intentflags, boolean execinfg,
            boolean whilerestarting, boolean permissionsreviewrequired)
            throws transactiontoolargeexception {
	    
	    //...

	    realstartservicelocked(r, app, execinfg);
	    
	    //...
    }

    //继续查看

    private final void realstartservicelocked(servicerecord r,
            processrecord app, boolean execinfg) throws remoteexception {
	    
	    //...

	    app.thread.schedulecreateservice(r, r.serviceinfo,
                    mam.compatibilityinfoforpackagelocked(r.serviceinfo.applicationinfo),
                    app.repprocstate);

            //...

	    sendserviceargslocked(r, execinfg, true);
	    
    }
第13行,servicerecord封装了要启动的服务一些信息,r作为方法的参数进行传递。

第62行,app.thread是一个iapplicationthread的代理对象,最终会调用applicationthread$schedulecreateservice方法启动服务,具体分析可以参考文章android activity的启动流程源码解析。内部会调用service$oncreate方法启动服务,后面会有所分析。

第68行,内部会调用onstartcommand方法,这里不做过多介绍,代码流程与oncreate类似。

三,启动服务的操作,交给activitythread来处理

继续app.thread.schedulecreateservice进行分析,值得一提的是,applicationthread是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;

    sendmessage(h.create_service, s);
}

 

查看activitythread$sendmessage源码如下:

private void sendmessage(int what, object obj) {
        sendmessage(what, obj, 0, 0, false);
}

//继续查看

private void sendmessage(int what, object obj, int arg1, int arg2, boolean async) {
        if (debug_messages) slog.v(
            tag, "schedule " + what + " " + mh.codetostring(what)
            + ": " + arg1 + " / " + obj);
        message msg = message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setasynchronous(true);
        }
        mh.sendmessage(msg);
}
第19行,handler发送了一个消息,于是启动服务的操作在消息的处理中了。

查看activitythread$handlemessage方法源码:

public void handlemessage(message msg) {
        if (debug_messages) slog.v(tag, ">>> handling: " + codetostring(msg.what));
        switch (msg.what) {
		
	    //...code

	    case create_service:
                trace.tracebegin(trace.trace_tag_activity_manager, ("servicecreate: " + string.valueof(msg.obj)));
                handlecreateservice((createservicedata)msg.obj);
                trace.traceend(trace.trace_tag_activity_manager);
                break;

	    //...code
	}			    	   	    
}
第9行,调用handlecreateservice方法启动服务。可以发现,启动服务的过程与启动activity的过程有相同地方,刚开始将启动组件的操作交给系统服务activitymanagerservice来出来,然后,将启动组件的操作交给applicationthread来处理。值得一提是,这两步都涉及到进程间的通信,且是基于binder机制,可以看到binder机制在framework层的利用无处不在。最后,处理组件的操作都是通过发送一次消息来完成,启动服务与启动activity具体做的操作比较相同,这也是为何文章开头建议先了解activity的启动流程。

 

继续查看activitythread$handlecreateservice方法源码:

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;
        application app = null;
        try {
            app = packageinfo.makeapplication(false, minstrumentation);
            java.lang.classloader cl = packageinfo.getclassloader();
            service = instantiate(cl, data.info.name, data.intent, app,
                    application::instantiateservice);
        } catch (exception e) {
            if (!minstrumentation.onexception(service, e)) {
                throw new runtimeexception(
                    "unable to instantiate service " + data.info.name
                    + ": " + e.tostring(), e);
            }
        }

        try {
            if (locallogv) slog.v(tag, "creating service " + data.info.name);

            contextimpl context = contextimpl.createappcontext(this, packageinfo);
            context.setoutercontext(service);

            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) {
            if (!minstrumentation.onexception(service, e)) {
                throw new runtimeexception(
                    "unable to create service " + data.info.name
                    + ": " + e.tostring(), e);
            }
        }
    }
仔细分析代码可以发现,启动服务最终调用了activity$handlecreateservice方法,与启动activity最终调用了activitythread$performlaunchactivity方法做的事情有些类似,详情参考文章android activity的启动流程源码解析。

handlecreateservice启动服务大致有操作:

第11行,创建application对象,若应用程序已经存在该对象,则不再创建。

第13行,通过类加载器classloader创建service的实例。

第26行,创建service的上下文环境,也就是创建contextimpl对象,会作为service$attach方法的参数传入。

第29行,调用service$attach方法,做初始化一些变量的操作。

第31行,调用service$oncreate方法启动服务。

第32行,将service的实例对象存入map集合中,执行service生命周期的其他方法时,可以在该集合中取出service实例。

上述操作,与启动activity的流程大体类似,每一步操作不再作细致分析,详细分析可以参考文章android activity的启动流程源码解析。

四,最后

可以发现,启动服务与启动activity的流程有很多类似之处,了解activity的启动流程,对于本篇的理解很有意义~ ^_^