1.應(yīng)用啟動(dòng)流程分析:
1.1流程
一個(gè)Activity的啟動(dòng)過程。以Launcher中啟動(dòng)一個(gè)App為例,比如在Launcher中我們點(diǎn)了一個(gè)圖標(biāo)啟動(dòng)一個(gè)App的Activity径缅,Launcher里會(huì)執(zhí)行:
Intent intent = new Intent("xxx");
startActivity(intent);
簡(jiǎn)單的說下大體流程溜哮,App與AMS交互流程主要分以下幾步:
1. 原App通知AMS要起一個(gè)新Activity。
2. AMS創(chuàng)建相應(yīng)數(shù)據(jù)結(jié)構(gòu)塘砸,然后通知WMS創(chuàng)建相應(yīng)數(shù)據(jù)結(jié)構(gòu),再通知原Activity暫停。
3. 原Activity暫停后通知AMS嗓奢。
4. AMS創(chuàng)建新App進(jìn)程,通知WMS新App可見浑厚,再通知App創(chuàng)建Activity等相應(yīng)數(shù)據(jù)結(jié)構(gòu)股耽。
首先分析下App端的結(jié)構(gòu)。移動(dòng)平臺(tái)一般顯示區(qū)域有限钳幅,要完成一個(gè)工作往往不是一屏內(nèi)容中能搞定的物蝙,所以Android中有了Activity的概念,讓用戶可以把相關(guān)的子內(nèi)容放到單獨(dú)的Activity中敢艰,然后通過Intent在Activity間跳轉(zhuǎn)诬乞。類似于瀏覽網(wǎng)頁,點(diǎn)擊鏈接跳轉(zhuǎn)到另一個(gè)網(wǎng)頁。這些同一交互過程中的一系列Activity成為一個(gè)Task丽惭。這些Activity運(yùn)行在主線程ActivityThread中击奶。Activity要展現(xiàn)出來的主視圖是DecorView,它是一棵視圖樹责掏。ViewRootImpl負(fù)責(zé)管理這個(gè)視圖樹和與WMS交互柜砾,與WMS交互通過WindowManagerImpl和WindowManagerGlobal。DecorView被包含在系統(tǒng)的通用窗口抽象類Window當(dāng)中换衬。視圖對(duì)應(yīng)的圖形緩沖區(qū)由Surface管理痰驱。
1.2主要類介紹
其中涉及到的主要的類包括下面幾個(gè):
AMS(ActivityManagerService)
Activity的管理者。其實(shí)除了Activity瞳浦,AMS也管Service等組件信息担映,另外AMS還管理Process信息。
Activity:描述一個(gè)Activity叫潦,它是與用戶交互的基本單元蝇完。
ActivityRecord:描述單個(gè)Activity,Activity堆棧中的基本單元矗蕊。
ActivityThread:每一個(gè)App進(jìn)程有一個(gè)主線程短蜕,它由ActivityThread描述。它負(fù)責(zé)這個(gè)App進(jìn)程中各個(gè)Activity的調(diào)度和執(zhí)行傻咖,以及響應(yīng)AMS的操作請(qǐng)求等朋魔。
ApplicationThread:AMS和Activity通過它進(jìn)行通信。對(duì)于AMS而言卿操,ApplicationThread代表了App的主線程警检。簡(jiǎn)而言之,它是AMS與ActivityThread進(jìn)行交互的接口害淤。注意ActivityThread和ApplicationThread之間的關(guān)系并不像Activity與Application扇雕。后者的關(guān)系是Application中包含了多個(gè)Activity,而前者ActivityThread和ApplicationThread是同一個(gè)東西的兩種"View"窥摄,ApplicationThread是在AMS眼中的ActivityThread洼裤。
ProcessRecord:描述一個(gè)App進(jìn)程,包含了該進(jìn)程中的Activity和Service列表溪王。
TaskRecord:TaskRecord中的mActivities是ActivityRecord的列表,它們是按照歷史順序排序的值骇。
ActivityStack:Activity堆棧莹菱,其中的ActivityRecord是通過TaskRecord這一層間接地被管理著。
ActivityStackSupervisor:ActivityStackSupervisor是ActivityStack的總管吱瘩。4.4中默認(rèn)引入了兩個(gè)ActivityStack道伟,一個(gè)叫Home stack,放Launcher和systemui,id為0蜜徽;另一個(gè)是Applicationstack祝懂,放App的Activity,id可能是任意值拘鞋。
ViewRootImpl:主要責(zé)任包括創(chuàng)建Surface砚蓬,和WMS的交互和App端的UI布局和渲染。同時(shí)負(fù)責(zé)把一些事件發(fā)往Activity以便Activity可以截獲事件盆色。每一個(gè)添加到WMS中的窗口對(duì)應(yīng)一個(gè)ViewRootImpl灰蛙,通過WindowManagerGlobal向WMS添加窗口時(shí)創(chuàng)建。大多數(shù)情況下隔躲,它管理Activity頂層視圖DecorView摩梧。總得來說宣旱,它相當(dāng)于MVC模型中的Controller仅父。
ViewRootImpl::W:用于向WMS提供接口,讓W(xué)MS控制App端的窗口浑吟。它可看作是個(gè)代理笙纤,很多時(shí)候會(huì)調(diào)用ViewRootImpl中的功能。這種內(nèi)嵌類的用法很多买置,特別是這種提供接口的代理類粪糙,如PhoneWindow::DecorView等。
Instrumentation:官方提供的Hook忿项,主要用于測(cè)試蓉冈。如果只關(guān)注窗口管理流程的話可以先無視。
WindowManagerImpl:Activity中與窗口管理系統(tǒng)通信的代理類轩触,實(shí)現(xiàn)類是WindowManagerGlobal寞酿。WindowManagerGlobal是App中全局的窗口管理模塊,因此是個(gè)Singleton脱柱。其中管理著該App中的ViewRootImpl伐弹,DecorView等結(jié)構(gòu)。
WMS(WindowManagerService)
窗口的管理者榨为。與AMS不同惨好,一些高層的App中的概念,如進(jìn)程等随闺,WMS是不care的日川。因?yàn)閃MS只對(duì)窗口進(jìn)行管理,哪個(gè)進(jìn)程的它不關(guān)心矩乐。像Activity這些概念在WMS仍然有龄句,因?yàn)锳ctivity對(duì)窗口的管理會(huì)產(chǎn)生影響回论。
WMS主要責(zé)任是維護(hù)窗口堆棧,計(jì)算每個(gè)窗口的layer信息交給SF分歇,替App申請(qǐng)和調(diào)整繪圖Surface傀蓉,當(dāng)窗口顯示狀態(tài)變化了還要通知其它模塊,另外還要處理系統(tǒng)輸入职抡。所以說葬燎,WMS可能是與其它模塊交互最多的模塊之一了。它與AMS繁调,App萨蚕,SF及Input等模塊都交集。Android中大體有以下幾種窗口類型:1.應(yīng)用窗口蹄胰,一般來說就是Activity的主窗口岳遥。但也有些情況App沒有Activity,直接把自定義的View添加到WMS中裕寨,比如浮動(dòng)窗口浩蓉。2.子窗口,需要有一個(gè)父窗口宾袜,如Context Menu捻艳,Option Menu,Popup Window和Dialog等庆猫。3.系統(tǒng)窗口认轨,如狀態(tài)欄,鎖屏窗口月培,輸入法窗口嘁字,壁紙窗口和Toast之流,由系統(tǒng)創(chuàng)建的杉畜,不依賴于父窗口纪蜒。
Window:每個(gè)App雖然都可以做得各不相同,但是作為有大量用戶交互的系統(tǒng)此叠,窗口之間必須要有統(tǒng)一的交互模式纯续,這樣才能減小用戶的學(xué)習(xí)成本。這些共性比如title, action bar的顯示和通用按鍵的處理等等灭袁。Window類就抽象了這些共性猬错。另外,它定義了一組Callback茸歧,Activity通過實(shí)現(xiàn)這些Callback被調(diào)用來處理事件兔魂。注意要和在WMS中的窗口區(qū)分開來,WMS中的窗口更像是App端的View举娩。
PhoneWindow:PhoneWindow是Window類的唯一實(shí)現(xiàn),至少目前是。這樣的設(shè)計(jì)下如果要加其它平臺(tái)的Window類型更加方便铜涉。每個(gè)Activity會(huì)有一個(gè)PhoneWindow智玻,在attach到ActivityThread時(shí)創(chuàng)建,保存在mWindow成員中芙代。
Context:運(yùn)行上下文吊奢,Activity和Service本質(zhì)上都是一個(gè)Context,Context包含了它們作為運(yùn)行實(shí)體的共性纹烹,如啟動(dòng)Activity页滚,綁定Service,處理Broadcast和Receiver等等铺呵。注意Application也會(huì)有Context裹驰。Activity的Context是對(duì)應(yīng)Activity的,Activity被殺掉(比如轉(zhuǎn)屏后)后就變了片挂。所以要注意如果有生命周期很長的對(duì)象有對(duì)Activity的Context的引用的話幻林,轉(zhuǎn)屏、返回這種會(huì)引起Activity銷毀的操作都會(huì)引起內(nèi)存泄露音念。而Application的Context生命周期是和App進(jìn)程一致的沪饺。關(guān)于Context的類結(jié)構(gòu)圖有下面的形式。Context是抽象類闷愤,定義了接口整葡。ContextImpl是Context的實(shí)現(xiàn)類,包含了實(shí)現(xiàn)讥脐。而ContextWrapper是Context的包裝類遭居,它把請(qǐng)求delegate給其中的ContextImpl類去完成。ContextThemeWrapper是ContextWrapper的裝飾類攘烛,它在ContextWrapper的基礎(chǔ)上提供了自定義的主題魏滚。這結(jié)構(gòu)初看有點(diǎn)亂,但結(jié)合下面的Decorator模式(java的設(shè)計(jì)模式)就一目了然了坟漱。
Surface:這是在App端管理圖形緩沖區(qū)的類鼠次,其中最重要的是圖形緩沖區(qū)隊(duì)列。經(jīng)由WMS從SF中得到IGraphicBufferProducer接口對(duì)象BufferQueue后芋齿,Surface便可以從該隊(duì)列中queue和dequeue圖形緩沖區(qū)腥寇。SurfaceControl在WMS中封裝了Surface以及與SF的交互。Canvas和Surface從字面意思上很像觅捆,但前者其實(shí)更確切地說不是“畫布”赦役,而是“畫家”。Surface中的圖形緩沖區(qū)才是App的畫布栅炒。
1.3結(jié)構(gòu)流程分析
從結(jié)構(gòu)上分析掂摔,應(yīng)用啟動(dòng)大體可以分為3塊:
1.ams啟動(dòng)的調(diào)用(見圖一)
2.應(yīng)用本身生命周期的調(diào)用(見圖二)
3.Wms畫圖的調(diào)用(見圖三)
簡(jiǎn)單的ams第一部分調(diào)用關(guān)系概括為:
ActivityStackSupervisor
->startActivityMayWait
->startActivityLocked
->startActivityUncheckedLocked
->resumeTopActivitiesLocked
->resumeTopActivitiesLocked
->resumeTopActivityLocked(ActivityRecord prev)?
->resumeTopActivityLocked(ActivityRecordprev,Bundleoptions)
->startSpecificActivityLocked
->mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);
它是從ams的startActivityAsUser開始术羔,主要為應(yīng)用創(chuàng)建各種對(duì)象信息,方便調(diào)用乙漓,比如ActivityInfo,ActivityRecord,Stack,TaskRecord對(duì)象级历,檢查調(diào)用者權(quán)限,檢查intent的合法性叭披,為intent找到相應(yīng)的應(yīng)用寥殖,把原activity暫停放入后臺(tái)task列表中,并且把ApplicationToken加入到wms的task隊(duì)列里面涩蜘。通知wms創(chuàng)建白色的過渡window嚼贡,方法為mWindowManager.setAppStartingWindow。
第二部分應(yīng)用生命周期的調(diào)用同诫,主要從ActvityThread的handleLaunchActivity開始粤策。
新啟動(dòng)的Activity的創(chuàng)建初始化主要是在handleLaunchActivity()中完成的。handleLaunchActivity()的作用是加載指定的Activity并運(yùn)行剩辟。這其中在App端主要是創(chuàng)建ActivityThread掐场,Activity,PhoneWindow贩猎,DecorView等對(duì)象熊户,并調(diào)用Activity生命周期中的onCreate(),onResume()函數(shù)執(zhí)行用戶邏輯吭服。正常點(diǎn)的App里onCreate里會(huì)調(diào)用setContentView設(shè)置主視圖嚷堡。setContentView()里主要是調(diào)用了installDecor(),其中會(huì)設(shè)置窗口的通用元素艇棕,如title, action bar之類蝌戒,還會(huì)把xml文件inflate成布局對(duì)象。
簡(jiǎn)單的調(diào)用關(guān)系概括為:
handleLaunchActivity
->performLaunchActivity
?->mInstrumentation.newActivity
-> activity.attach
->mInstrumentation.callActivityOnCreate?
?->activity.onCreate
-> activity.performStart()
->handleResumeActivity
->wm.addView(decor, l);
可以看到這時(shí)創(chuàng)建了DecorView沼琉,這便是Activity的主窗口的頂層視圖北苟。DecorView創(chuàng)建好后,handleResumeActivity()中會(huì)將它添加到WMS中去打瘪。當(dāng)App向WMS添加窗口時(shí)友鼻,會(huì)調(diào)用WindowManagerImpl的addView()。注意WindowManagerImpl中的addView()函數(shù)和ViewGroup里的addView()函數(shù)完全不一樣闺骚,后者是將View加入到本地的View組織架構(gòu)中去彩扔,和WMS沒有關(guān)系。
第三部分主要從addView()的流程如下:
首先通過WindowManagerImpl的addView()會(huì)創(chuàng)建對(duì)應(yīng)的ViewRootImpl僻爽,然后ViewRootImpl申請(qǐng)WMS得到Session(如果是App第一個(gè)Activity會(huì)新建)虫碉,其接口為IWindowSession,然后ViewRootImpl通過addToDisplay()把自己的ViewRootImpl::W(實(shí)現(xiàn)了IWindow接口)注冊(cè)給WMS胸梆。addView()的工作主要包括創(chuàng)建ViewRootImpl敦捧,和遠(yuǎn)程WMS建立Session须板,并將當(dāng)前視圖注冊(cè)到WMS這幾步【ぢ眩可以看到App端通過WindowManagerGlobal調(diào)用addView()逼纸,調(diào)用鏈到WMS就變成addWindow(),概念發(fā)生了改變济蝉,這也印證上面提到的App端和WMS端的Window概念不一樣的說法。
2.Process流程
2.1進(jìn)程啟動(dòng)
進(jìn)程的啟動(dòng)的入口函數(shù)是AMS.startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags,String hostingType, ComponentName hostingName, boolean allowWhileBooting,boolean isolated, boolean keepIfLarge)菠发。在前面的文章中知道王滤,當(dāng)啟動(dòng)Activity、Service滓鸠、getContentProvider時(shí)如果目標(biāo)進(jìn)程未啟動(dòng)雁乡,那么就需要調(diào)用startProcessLocked()來啟動(dòng)目標(biāo)進(jìn)程。所有線程啟動(dòng)都是通過這里啟動(dòng)糜俗,包括activity踱稍,Service、Provider悠抹、Broadcast珠月。
2.1.1?AMS.startProcessLocked()
final ProcessRecord startProcessLocked(){
......
? ? startProcessLocked(app, hostingType, hostingNameStr);
.......
}
private?final?void?startProcessLocked(ProcessRecord app,String hostingType, String hostingNameStr) {
? ? ?// Start the process. ?It will either succeed and return a result containing
? ? // the PID of the new process, or else throw a RuntimeException.
? ? ?Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
? ? app.processName, uid, uid, gids, debugFlags, mountExternal,
? ? app.info.targetSdkVersion, app.info.seinfo,null);
}
1.調(diào)用Process.start("android.app.ActivityThread")來啟動(dòng)ActivityThread的線程,并在等待PROC_START_TIMEOUT時(shí)間后楔敌,查看線程時(shí)候啟動(dòng)超時(shí)啤挎。
2.start函數(shù)直接調(diào)用Process.startViaZygote()-->zygoteSendArgsAndGetResult(),進(jìn)程是從Zygote中孵化出來的卵凑。
3.Zygote是向socket服務(wù)端寫數(shù)據(jù)庆聘,把創(chuàng)建進(jìn)程的請(qǐng)求通過socket通訊方式來讓framework的進(jìn)程孵化類zygote創(chuàng)建新進(jìn)程。而數(shù)據(jù)就是argsForZygote——一個(gè)以字符串List形式的把Process.start()所有調(diào)用參數(shù)都包含在里面的變量勺卢。
socket服務(wù)端收到創(chuàng)建新進(jìn)程的請(qǐng)求伙判,ZygoteConnection.runOnce()接收到新進(jìn)程的參數(shù),然后調(diào)用Zygote.forkAndSpecialize()來fork一個(gè)子進(jìn)程黑忱,在子進(jìn)程中會(huì)接著關(guān)閉socket宴抚,調(diào)用ZygoteInit.invokeStaticMain(cloader, className, mainArgs),即調(diào)用ActivityThread.main()杨何。新的應(yīng)用進(jìn)程會(huì)從ActivityThread的main()函數(shù)處開始執(zhí)行酱塔。
2.1.2?ActivityThread.main()
startProcessLocked方法后面就調(diào)用了ActivityThread.main,啟動(dòng)ActivityThread.attach()危虱。
public?static?void?main(String[] args) {
? ? ?Process.setArgV0("");
? ? ? Looper.prepareMainLooper();
? ? ?ActivityThread thread =newActivityThread();
? ? ?thread.attach(false);
}
private?void?attach(booleansystem) {
? ? sCurrentActivityThread=this;
? ? mSystemThread= system;
? ?if(!system) {
? ? ?RuntimeInit.setApplicationObject(mAppThread.asBinder());
? ? ? IActivityManager mgr = ActivityManagerNative.getDefault();
? ? ? mgr.attachApplication(mAppThread);
? ?}else{
? ......
}
2.1.3?AMS.attachApplicationLocked()
attachApplicationLocked()函數(shù)主要做一些新進(jìn)程起來后的工作羊娃,比如設(shè)置ProcessRecord信息、獲取ContentProvider信息返回給ActivityThread埃跷、啟動(dòng)該進(jìn)程的Activity蕊玷、Service邮利、BroadCast等工作(四大組件相關(guān)),下面是詳細(xì)分析垃帅。
1.在調(diào)用startProcessLocked()啟動(dòng)進(jìn)程時(shí)延届,便將ProcessRecord和Pid加入mPidsSelfLocked中,故此時(shí)app不為null贸诚。
2.啟動(dòng)應(yīng)用所包含的ContentProvider方庭,相當(dāng)于將ContentProvider注冊(cè)到AMS中來,然后再把返回的參數(shù)providers傳給ActivityThread酱固,ActivityThread根據(jù)參數(shù)加載對(duì)應(yīng)的ContentProvider到應(yīng)用進(jìn)程中來械念,應(yīng)用進(jìn)程加載ContentProvider完成后會(huì)調(diào)用AMS.publishContentProviders()將ContentProvider信息公開。(如果應(yīng)用包含有provider的信息运悲,被oom強(qiáng)制殺死時(shí)會(huì)自動(dòng)重啟線程)
3.保證應(yīng)用的dex龄减,只有在特殊的運(yùn)行“沒有預(yù)先dexopt”模式才有作用。
4.AMS側(cè)對(duì)該進(jìn)程進(jìn)行一些初始化操作后邊將一些必要信息傳給ActivityThread班眯,這個(gè)步驟對(duì)應(yīng)用非常重要希停,應(yīng)用很多初始化的數(shù)據(jù)都在這里生成,包括初始化時(shí)區(qū)署隘,設(shè)置資源宠能,density,dpi定踱,cache目錄信息棍潘,虛擬器大小等。
5.進(jìn)程起來后崖媚,調(diào)用ActivityStackSupervisor.attachApplicationLocked來啟動(dòng)相應(yīng)Activity亦歉。如果未啟動(dòng)的Activity要跑在當(dāng)前啟動(dòng)的進(jìn)程中,那么直接調(diào)用realStartActivityLocked()來啟動(dòng)當(dāng)前畅哑,realStartActivityLocked就是啟動(dòng)Activity的真正函數(shù)肴楷。
6.進(jìn)程起來后調(diào)用ActiveServices.attachApplicationLocked()啟動(dòng)相應(yīng)服務(wù),尋找要在當(dāng)前進(jìn)程中啟動(dòng)的Activity荠呐,并啟動(dòng)之赛蔫。mPendingServices中保存著等待該進(jìn)程啟動(dòng)的Service,現(xiàn)在進(jìn)程已經(jīng)啟動(dòng)了泥张,所以mPendingServices中保存的服務(wù)也可以啟動(dòng)了呵恢,即在下面調(diào)用realStartServiceLocked()來啟動(dòng)服務(wù)。
7.處理廣播媚创,將原本要發(fā)到當(dāng)前進(jìn)程的廣播處理掉渗钉,調(diào)用isPendingBroadcastProcessLocked()來判斷當(dāng)前啟動(dòng)的進(jìn)程是否是PendingBroadcast等待的進(jìn)程,如果是就把PendingBroadcast廣播發(fā)送給當(dāng)前這個(gè)進(jìn)程中去。