




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、在编写Android应用程序时,我们一般将一些计算型的逻辑放在一个独立的进程来处理,这样主进程仍然可以流畅地响应界面事件,提高用户体验。Android系统为我们提供了一个Service类,我们可以实现一个以Service为基类的服务子类,在里面实现自己的计算型逻辑,然后在主进程通过startService函数来启动这个服务。在本文中,将详细分析主进程是如何通过startService函数来在新进程中启动自定义服务的。在主进程调用startService函数时,会通过Binder进程间通信机制来通知ActivitManagerService来创建新进程,并且启动指定的服务。在Android系统中
2、,Binder进程间通信机制使用非常广泛,因此,希望读者在继续阅读下面的内容之前,对Android系统和Binder进程间通信机制有一定的了解,具体可以参考前面Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。关于startService的具体用法,可以参考前面Android系统匿名共享内存Ashmem(AnonymousSharedMemory)简要介绍和学习计划一文中用到的实例,它是Activity类的一个成员函数:viewplain1.packageshy.luo.ashmem;.publicclassClientextendsActivityimp
3、lementsOnClickListener6.7.IMemoryServicememoryService=null;8.9.10.Override11.publicvoidonCreate(BundlesavedInstanceState)12.13.14.IMemoryServicems=getMemoryService();15.if(ms=null)16.startService(newIntent("shy.luo.ashmem.server");17.else18.Log.i(LOG_TAG,"MemoryServicehasstarted."
4、;);2.23.Log.i(LOG_TAG,"ClientActivityCreated.");25.26.27.)这里的"shy.luo.ashmem.server是在程序配置文件AndroidManifest.xml配置的Service的名字,用来告诉Android系统它所要启动的服务的名字:viewplain1. <manifestxmlns:android="2. package="shy.luo.ashmem"3. android:sharedUserId="android.uid.sys
5、tem"4. android:versionCode="1"5.android:versionName="1.0">6. <applicationandroid:icon=p_name">7. ."drawable/icon"android:label=string/ap8. <service9. android:enabled="true"10. android:name=".Server"11. android:process=".Ser
6、ver'12. <intent-filter>13. <actionandroid:name=14. <categoryandroid:name=ULT"/>15. </intent-filter>>"shy.luo.ashmem.server"/>"ent.category.DEFA16. </service>17. </application>18. </manifest>这里,名字“shy.luo.ashmem.server对应的
7、服务类为shy.luo.ashmem.Server,下面语句:viewplain1.startService(newIntent("shy.luo.ashmem.server");就表示要在一个新的进程中启动shy.luo.ashmem.Server这个服务类,它必须继承于Android平台提供的Service类:viewplain1. packageshy.luo.ashmem;2.3.1从图中可以看出,Activity继承了Contextwrapper类,而在Contextwrapper类中,实现了startService函数。在Contextwrapper类中,有一个
8、成员变量mBase,卜面,我们来看看Activity类中的startService成员函数是如何实现的先来看看Activity的类图:.1.publicclassServerextendsServiceDatai图1RaturtScr的皿acrvicc;Inrtcrrt);CfflnpsnenlNjimc4starrservice;service:君meCort口或叩pqrISllHlrtl-i-1ranssat(cade:irt,dais:FBrcai(:Psrc>el.Ibb:irft:bHlear
9、OverridepublicIBinderonBind(Intentintent)returnnullOverridepublicvoidonCreate()日trrmTActiwitySrUt训mpl+s:artSeiiceistrvic巴.Intsnt1:C匚mponentharneBindwPr。仃-nOtjiectimgdqirtdaiq.Paiccl.icy%pH口口耨.时:;boM型同ctiwityMiEg心rPrxy4如H。*FlHlJr-l4人丽加川仙口州PfdhYrtma#Eindar卜calfer-lApplcstcnT-1jr|?eix>jc:»'
10、Intern,rwO'VcType:Strng'匚qipcrEFgn正IMivitMariiflg«r产ENFfHHIApplet!CTlTTMd£Blvl££FIr1口I-yITyp-S|rij-11eIrIH11"它是一个Contextlmpl实例,而Contextlmpl类和Contextwrapper类一样继承于Context类,Contextwrapper类的startService函数最终过调用Contextlmpl类的startService函数来实现。这种类设计方法在设计模式里面,就称之为装饰模式(Decorat
11、or),或者包装模式(Wrapper)。在Contextlmpl类的startService类,最终又调用了ActivityManagerProxy类的startService来实现启动服务的操作,看到这里的Proxy关键字,回忆一下前面Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析这篇文章,就会知道ActivityManagerProxy是一个Binder对象的远程接口了,而这个Binder对象就是我们前面所说的ActivityManagerService了。这个ActivityManagerService类实现在frameworks/base/serv
12、ices/java/com/android/server/am/ActivityManagerService.java文件中,它是Binder进程间通信机制中的Server角色,它是随机启动的。随机启动的Server是在frameworks/base/services/java/com/android/server/SystemServer.java文件里面进行启动的,我们来看一下ActivityManagerService启动相关的代码:viewplain1. classServerThreadextendsThread. Override6. publicvoidrun()7
13、.8. 9.10. /Criticalservices.11. try12.13. .14.15. context=ActivityManagerService.main(factoryTest);16.17. .18.19. ActivityManagerService.setSystemProcess();20.21. .22.23. catch(RuntimeExceptione)7.28.Slog.e()"System","Failurestartingcoreservice'29. 30.31. .32.33. 首先是调用Ac
14、tivityManagerService.main函数来创建一个ActivityManagerService实例,然后通过调用ActivityManagerService.setSystemProcess函数把这个Binder实例添加Binder进程间通信机制的守护进程ServiceManager中去:viewplain.5.publicfinalclassActivityManagerServiceextendsActivityManagerNativeimplementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback6.7.
15、3.24.25.staticActivityManagerServicemSelf;publicstaticvoidsetSystemProcess()tryActivityManagerServicem=mSelf;ServiceManager.addService("activity",m);catch(PackageManager.NameNotFoundExceptione)publicstaticfinalContextmain(intfactoryTest)28.29. Ac
16、tivityManagerServicem=thr.mService;30. mSelf=m;31.32. .33.34. 35. 这样,ActivityManagerService就启动起来了。回到ActivityManagerProxy类的startService函数中,它定义在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:viewplain1. classActivityManagerProxyimplementsIActivityManager2. 3.4.5. publicComponentNa
17、mestartService(IApplicationThreadcaller,Intentservice,6. StringresolvedType)throwsRemoteException7. 8. Parceldata=Parcel.obtain();9. Parcelreply=Parcel.obtain();10. data.writeInterfaceToken(IActivityManager.descriptor);11. data.writeStrongBinder(caller!=null?caller.asBinder():null);12. service.write
18、ToParcel(data,0);13. data.writeString(resolvedType);14. mRemote.transact(START_SERVICE_TRANSACTION,data,reply,0);15. reply.readException();16. ComponentNameres=ComponentName.readFromParcel(reply);17. data.recycle();18. reply.recycle();19. returnres;20. 21.22.23. 参数service是一个Intent实例,它里面指定了要启动的服务的名称,
19、就是前面我们所说的"shy.luo.ashmem.server”了。参数caller是一个lApplicationThread实例,它是一个在主进程创建的一个Binder对象。在Android应用程序中,每一个进程都用一个ActivityThread实例来表示,而在ActivityThread类中,有一个成员变量mAppThread,它是一个ApplicationThread实例,实现了lApplicationThread接口,它的作用是用来辅助ActivityThread类来执行一些操作,这个我们在后面会看到它是如何用来启动服务的。参数resolvedType是一个字符串,它表示s
20、ervice这个Intent的MIME类型,它是在解析Intent时用到的。在这个例子中,我们没有指定这个Intent的MIME类型,因此,这个参数为nulloActivityManagerProxy类的startService函数把这三个参数写入到data本地变量去,接着通过mRemote.transact函数进入到Binder驱动程序,然后Binder驱动程序唤醒正在等待Client请求的ActivityManagerService进程,最后进入到ActivityManagerService的startService函数中。ActivityManagerService的startServi
21、ce函数的处理流程如下图所示:点击查看大图在这个序列图中,一共有20个步骤,下面说明每一步。Step1.ActivityManagerService.startService这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1.publicfinalclassActivityManagerServiceextendsActivityManagerNative2.implementsWatchdog.Monitor,BatteryStatsImpl.
22、BatteryCallback. publicComponentNamestartService(IApplicationThreadcaller,Intentservice,7. StringresolvedType)8. /Refusepossibleleakedfiledescriptors9. if(service!=null&&service.hasFileDescriptors()=true)10. thrownewIllegalArgumentException("FiledescriptorspassedinIntent");1
23、1. 12.13. synchronized(this)14. finalintcallingPid=Binder.getCallingPid();15. finalintcallingUid=Binder.getCallingUid();16. finallongorigId=Binder.clearCallingIdentity();17. ComponentNameres=startServiceLocked(caller,service,18. resolvedType,callingPid,callingUid);19. Binder.restoreCallingIdentity(o
24、rigId);20. returnres;21. 22. 6. 这里的参数caller、service和resolvedType分别对应ActivityManagerProxy.startService传进来的三个参数。Step2.ActivityManagerService.startServiceLocked这个函数同样定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. publicfinalclassActivityManag
25、erServiceextendsActivityManagerNative2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3.46. ComponentNamestartServiceLocked(IApplicationThreadcaller,7. Intentservice,StringresolvedType,8. intcallingPid,intcallingUid)9. synchronized(this)10. .11.12. ServiceLookupResultres=13. retrieveSer
26、viceLocked(service,resolvedType,14. callingPid,callingUid);15.16. .17.18. ServiceRecordr=res.record;19.20. .21.22. if(!bringUpServiceLocked(r,service.getFlags(),false)23. returnnewComponentName("!","Serviceprocessisbad");24. 25. ;26. 27. 1. 函数首先通过retrieveSer
27、viceLocked来解析service这个Intent,就是解析前面我们在AndroidManifest.xml定义的Service标签的intent-filter相关内容,然后将解析结果放在res.record中,然后继续调用bringUpServiceLocked进一步处理。Step3.ActivityManagerService.bringUpServiceLocked这个函数同样定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. public
28、finalclassActivityManagerServiceextendsActivityManagerNative2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3.46. privatefinalbooleanbringUpServiceLocked(ServiceRecordr,7. intintentFlags,booleanwhileRestarting)8.9. .10.11. finalStringappName=cessName;12.13. .14.15. /Notrunning-get
29、itstarted,andenqueuethisservicerecord16. /tobeexecutedwhentheappcomesup.17. if(startProcessLocked(appName,r.appInfo,true,intentFlags,18. "service",,false)=null)19.20. .21.22. returnfalse;23. 24.25. if(!mPendingServices.contains(r)26. mPendingServices.add(r);27. 28.29. returntrue;30.3
30、1. 5. 这里的appName便是我们前面在AndroidManifest.xml文件定义service标签时指定的android:process属性值了,即“.Server。"接着调用startProcessLocked函数来创建一个新的进程,以便加载自定义的Service类。最后将这个ServiceRecord保存在成员变量mPendingServices列表中,后面会用到。Step4.ActivityManagerService.startProcessLocked这个函数同样定义在frameworks/base/services/java/com/and
31、roid/server/am/ActivityManagerService.java文件中:viewplain1.publicfinalclassActivityManagerServiceextendsActivityManagerNative2.implementsWatchdog.Monitor,BatteryStatsImpl.Ba3.4.5.tteryCallback6.7.privatefinalvoidstartProcessLocked(ProcessRecordapp,StringhostingType,StringhostingNameStr)1.try12
32、.13.14.15.intpid=Process.start("android.app.ActivityThread"16.mSimpleProcessManagement?cessName:nul0.l,uid,uid,gids,debugFlags,null);21.if(pid=0|pid=MY_PID)5.elseif(pid>0)26.27.app.pid=pid;app.removed=false;28.synchronized(mPidsSelfLocked)29.this.mPidsSelfLock
33、ed.put(pid,app);30.31.32.else6.37.catch(RuntimeExceptione)1.43. )7. )这里调用Process.start函数创建了一个新的进程,指定新的进程执行android.app.ActivityThread类。最后将表示这个新进程的ProcessRecord保存在mPidSelfLocked列表中,后面会用到。Step5.Process.start这个函数定义在frameworks/base/core/java/android/os/Process.java文件中,这个函数我们
34、就不看了,有兴趣的读者可以自己研究一下。在这个场景中,它就是新建一个进程,然后导入android.app.ActivityThread这个类,然后执行它的main函数。Step6.ActivityThread.main这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:viewplain1. publicfinalclassActivityThread. publicstaticfinalvoidmain(String口args)6.7. .8.9. Looper.prepareMainLoope
35、r();10.11. .12.13. ActivityThreadthread=newActivityThread();14. thread.attach(false);15.16. .17.18. Looper.100P();19.20. .21.23.24. .25. )26. 注意,执行到这里的时候,已经是在上一步创建的新进程里面了,即这里的进程是用来启动服务的,原来的主进程已经完成了它的命令,返回了。前面我们提到,在Android应用程序中,每一个进程对应一个ActivityThread实例,所以,这个函数会创建一个thread实例,然后调用ActivityThread.attach函
36、数进一步处理。Step7.ActivityThread.attach这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:viewplain1.publicfinalclassActivityThread. privatefinalvoidattach(booleansystem)6.7. .8.9. if(!system)10.11. .12.13. IActivityManagermgr=ActivityManagerNative.getDefault();14. try15. mgr.atta
37、chApplication(mAppThread);16. catch(RemoteExceptionex)17. 18. else19.20. .21.22. 23.24. .25.26. 28.29.30. 从Step6中,这里传进来的参数system为false。成员变量mAppThread是一个ApplicationThread实例,我们在前面已经描述过这个实例的作用,它是用来辅助ActivityThread来执行一些操作的。调用ActivityManagerNative.getDefault函数得到ActivityManagerService的远程接口,即ActivityManage
38、rProxy,接着调用它的attachApplication函数。Step8.ActivityManagerProxy.attachApplication这个函数定义在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:viewplain1. classActivityManagerProxyimplementsIActivityManager2. 3.4.5. publicvoidattachApplication(IApplicationThreadapp)throwsRemoteException6. 7
39、. Parceldata=Parcel.obtain();8. Parcelreply=Parcel.obtain();9. data.writeInterfaceToken(IActivityManager.descriptor);10. data.writeStrongBinder(app.asBinder();11. mRemote.transact(ATTACH_APPLICATION_TRANSACTION,data,reply,0);12. reply.readException();13. data.recycle();14. reply.recycle();15. 16.17.
40、18.19. 这个函数主要是将新进程里面的IApplicationThread实例通过Binder驱动程序传递给ActivityManagerService。Step9.ActivityManagerService.attachApplication这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. publicfinalclassActivityManagerServiceextendsActivityManagerNative2. impl
41、ementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3.45.6.publicfinalvoidattachApplication(IApplicationThreadthread)7.8. synchronized(this)9. intcallingPid=Binder.getCallingPid();10. finallongorigId=Binder.clearCallingIdentity();11. attachApplicationLocked(thread,callingPid);12. Binder.restoreCa
42、llingIdentity(origId);13. 14. 15. 1617. 18.这里通过调用attachApplicationLocked函数进一步处理。Step10.ActivityManagerService.attachApplicationLocked这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. publicfinalclassActivityManagerServiceextendsActivityManagerNativ
43、e2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3.45.6.privatefinalbooleanattachApplicationLocked(IApplicationThreadthread,8. /Findtheapplicationrecordthatisbeingattached.eithervia9. /thepidifwearerunninginmultipleprocesses,orjustpullthe10. /nextapprecordifweareemulatingprocesswithano
44、nymousthreads.11. ProcessRecordapp;12. if(pid!=MY_PID&&pid>=0)13. synchronized(mPidsSelfLocked)14. app=mPidsSelfLocked.get(pid);15. 16. elseif(mStartingProcesses.size()>0)17. app=mStartingProcesses.remove(0);18. app.setPid(pid);19. else20. app=null;21. 22.23. .24.25.26. StringprocessNa
45、me=cessName;27.28. .29.30. app.thread=thread;31.32. .33.34. booleanbadApp=false;35.36. .37.38. /Findanyservicesthatshouldberunninginthisprocess.39. if(!badApp&&mPendingServices.size()>0)40. ServiceRecordsr=null;41. try42. for(inti=0;i<mPendingServices.size();i+)43. sr=mPendingSe
46、rvices.get(i);44. if(.uid!=sr.appInfo.uid45. |!processName.equals(cessName)46. continue;47. 48.49. mPendingServices.remove(i);50. i-;51. realStartServiceLocked(sr,app);52. didSomething=true;53. 54. catch(Exceptione)55.56. .57.58. 59. 60.61. .62.63. returntrue;64. 8. 回忆一下在上面的S
47、tep4中,以新进程的pid值作为key值保存了一个ProcessRecord在mPidsSelfLocked列表中,这里先把它取出来,存放在本地变量app中,并且将cessName保存在本地变量processName中。再回忆一下在上面的Step3中,在成员变量mPendingServices中,保存了一个ServiceRecord,这里通过进程uid和进程名称将它找出来,然后通过realStartServiceLocked函数来进一步处理。Step11.ActivityManagerService.realStartServiceLocked这个函数定义在frameworks
48、/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. classActivityManagerProxyimplementsIActivityManager2. 3.4.5. privatefinalvoidrealStartServiceLocked(ServiceRecordr,6. ProcessRecordapp)throwsRemoteException7.8. .10. r.app=app;11.12. .13.14. try15.16. .17.18. app.th
49、read.scheduleCreateService(r,r.serviceInfo);19.20. .21.22. finally23.24. .25.26. 27.28. .29.30. 4. 这里的app.thread是一个ApplicationThread对象的远程接口,它是在上面的Step6创建ActivityThread对象时作为ActivityThread对象的成员变量同时创建的,然后在Step9中传过来的。然后调用这个远程接口的scheduleCreateService函数回到原来的ActivityThread对象中执行启动服务的操作。Step12.Appl
50、icationThreadProxy.scheduleCreateService这个函数定义在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:viewplain1. classApplicationThreadProxyimplementsIApplicationThread2.5. publicfinalvoidscheduleCreateService(IBindertoken,Serviceinfoinfo)6. throwsRemoteException7. Parceldata=Parcel.
51、obtain();8. data.writeinterfaceToken(IApplicationThread.descriptor);9. data.writeStrongBinder(token);10. info.writeToParcel(data,0);11. mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION,data,null12. IBinder.FLAG_ONEWAY);13. data.recycle();14. 8. 这里通过Binder驱动程序回到新进程的ApplicationThread对象中去
52、执行scheduleCreateService函数。Step13.ApplicationThread.scheduleCreateService这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:viewplain1. publicfinalclassActivityThread. privatefinalclassApplicationThreadextendsApplicationThreadNative6.7. .8.9. publicfinalvoidscheduleCreateServi
53、ce(IBindertoken,10. ServiceInfoinfo)11. CreateServiceDatas=newCreateServiceData();12. s.token=token;13. =info;14.15. queueOrSendMessage(H.CREATE_SERVICE,s);16. 17. .18.19. 3. 这里调用ActivityThread的queueOrSendMessage将一个CreateServiceData数据放到消息队列中去,并且分开这个消息。注意,这里已经是在上面Step4创建的新进程中执行了。Step14.ActivityThread.queueOrSendMessage这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:viewplain1. publicfinalclassActivityThread. privatefinalvoidqueueOrSendMessage(intwhat,Objec
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 七彩课堂下册数学试卷
- 政府茶叶采摘活动方案策划(3篇)
- 五一饮料促销活动方案策划(3篇)
- 气泡焊接施工方案(3篇)
- 云南白酒酒窖施工方案(3篇)
- 隐蔽工程房屋施工方案(3篇)
- 心理电影剪辑活动策划方案(3篇)
- 基础安全施工方案(3篇)
- 住宅夹层施工方案(3篇)
- 老年骨质疏松症的护理
- 2025湖南湘潭湘乡市融媒体中心招聘事业单位工作人员10人笔试备考题库及答案解析
- 2025至2030中国婚庆行业发展趋势分析与未来投资战略咨询研究报告
- 2025年职业病诊断医师资格考试(职业性化学中毒)历年参考题库含答案详解(5卷)
- 健康管理师二级《理论知识》模拟考试试卷附答案
- 2025年安徽高考生物试题及答案
- 2025年国际汉语教师资格考试(对外汉语教学理论)历年参考题库含答案详解(5套)
- 2025年高校机房管理试题及答案
- ESG基础知识培训课件
- 泌尿系统常见疾病科普讲座
- 2025湖南省全日制用工劳动合同书
- 2025年中国南海研究院招聘事业编制人员考试笔试试题
评论
0/150
提交评论