Android Service的启动流程源码分析
一,写在前面
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的启动流程,对于本篇的理解很有意义~ ^_^
下一篇: 荀攸:曹魏第一任尚书令,最终结局是什么?
推荐阅读
-
Android 截图功能源码的分析
-
Android getJSONObject与optJSONObject的区别结合源码分析
-
Android 截图功能源码的分析
-
Android getJSONObject与optJSONObject的区别结合源码分析
-
Android 2.3 拨号上网流程从源码角度进行分析
-
Android中打电话的数据流程分析
-
Android 启动 Service(startservice和bindservice) 两种方式的区别
-
android的消息处理机制(图文+源码分析)—Looper/Handler/Message
-
android开发环境遇到adt无法启动的问题分析及解决方法
-
解析Android中如何做到Service被关闭后又自动启动的实现方法