1.應用啟動流程分析:
1.1流程
一個Activity的啟動過程。以Launcher中啟動一個App為例,比如在Launcher中我們點了一個圖標啟動一個App的Activity,Launcher里會執(zhí)行:
Intent intent = new Intent("xxx");
startActivity(intent);
簡單的說下大體流程,App與AMS交互流程主要分以下幾步:
1. 原App通知AMS要起一個新Activity。
2. AMS創(chuàng)建相應數(shù)據(jù)結(jié)構,然后通知WMS創(chuàng)建相應數(shù)據(jù)結(jié)構,再通知原Activity暫停。
3. 原Activity暫停后通知AMS。
4. AMS創(chuàng)建新App進程,通知WMS新App可見,再通知App創(chuàng)建Activity等相應數(shù)據(jù)結(jié)構。
首先分析下App端的結(jié)構。移動平臺一般顯示區(qū)域有限,要完成一個工作往往不是一屏內(nèi)容中能搞定的,所以Android中有了Activity的概念,讓用戶可以把相關的子內(nèi)容放到單獨的Activity中,然后通過Intent在Activity間跳轉(zhuǎn)。類似于瀏覽網(wǎng)頁,點擊鏈接跳轉(zhuǎn)到另一個網(wǎng)頁。這些同一交互過程中的一系列Activity成為一個Task。這些Activity運行在主線程ActivityThread中。Activity要展現(xiàn)出來的主視圖是DecorView,它是一棵視圖樹。ViewRootImpl負責管理這個視圖樹和與WMS交互,與WMS交互通過WindowManagerImpl和WindowManagerGlobal。DecorView被包含在系統(tǒng)的通用窗口抽象類Window當中。視圖對應的圖形緩沖區(qū)由Surface管理。
1.2主要類介紹
其中涉及到的主要的類包括下面幾個:
AMS(ActivityManagerService)
Activity的管理者。其實除了Activity,AMS也管Service等組件信息,另外AMS還管理Process信息。
Activity:描述一個Activity,它是與用戶交互的基本單元。
ActivityRecord:描述單個Activity,Activity堆棧中的基本單元。
ActivityThread:每一個App進程有一個主線程,它由ActivityThread描述。它負責這個App進程中各個Activity的調(diào)度和執(zhí)行,以及響應AMS的操作請求等。
ApplicationThread:AMS和Activity通過它進行通信。對于AMS而言,ApplicationThread代表了App的主線程。簡而言之,它是AMS與ActivityThread進行交互的接口。注意ActivityThread和ApplicationThread之間的關系并不像Activity與Application。后者的關系是Application中包含了多個Activity,而前者ActivityThread和ApplicationThread是同一個東西的兩種"View",ApplicationThread是在AMS眼中的ActivityThread。
ProcessRecord:描述一個App進程,包含了該進程中的Activity和Service列表。
TaskRecord:TaskRecord中的mActivities是ActivityRecord的列表,它們是按照歷史順序排序的。
ActivityStack:Activity堆棧,其中的ActivityRecord是通過TaskRecord這一層間接地被管理著。
ActivityStackSupervisor:ActivityStackSupervisor是ActivityStack的總管。4.4中默認引入了兩個ActivityStack,一個叫Home stack,放Launcher和systemui,id為0;另一個是Applicationstack,放App的Activity,id可能是任意值。
ViewRootImpl:主要責任包括創(chuàng)建Surface,和WMS的交互和App端的UI布局和渲染。同時負責把一些事件發(fā)往Activity以便Activity可以截獲事件。每一個添加到WMS中的窗口對應一個ViewRootImpl,通過WindowManagerGlobal向WMS添加窗口時創(chuàng)建。大多數(shù)情況下,它管理Activity頂層視圖DecorView??偟脕碚f,它相當于MVC模型中的Controller。
ViewRootImpl::W:用于向WMS提供接口,讓WMS控制App端的窗口。它可看作是個代理,很多時候會調(diào)用ViewRootImpl中的功能。這種內(nèi)嵌類的用法很多,特別是這種提供接口的代理類,如PhoneWindow::DecorView等。
Instrumentation:官方提供的Hook,主要用于測試。如果只關注窗口管理流程的話可以先無視。
WindowManagerImpl:Activity中與窗口管理系統(tǒng)通信的代理類,實現(xiàn)類是WindowManagerGlobal。WindowManagerGlobal是App中全局的窗口管理模塊,因此是個Singleton。其中管理著該App中的ViewRootImpl,DecorView等結(jié)構。
WMS(WindowManagerService)
窗口的管理者。與AMS不同,一些高層的App中的概念,如進程等,WMS是不care的。因為WMS只對窗口進行管理,哪個進程的它不關心。像Activity這些概念在WMS仍然有,因為Activity對窗口的管理會產(chǎn)生影響。
WMS主要責任是維護窗口堆棧,計算每個窗口的layer信息交給SF,替App申請和調(diào)整繪圖Surface,當窗口顯示狀態(tài)變化了還要通知其它模塊,另外還要處理系統(tǒng)輸入。所以說,WMS可能是與其它模塊交互最多的模塊之一了。它與AMS,App,SF及Input等模塊都交集。Android中大體有以下幾種窗口類型:1.應用窗口,一般來說就是Activity的主窗口。但也有些情況App沒有Activity,直接把自定義的View添加到WMS中,比如浮動窗口。2.子窗口,需要有一個父窗口,如Context Menu,Option Menu,Popup Window和Dialog等。3.系統(tǒng)窗口,如狀態(tài)欄,鎖屏窗口,輸入法窗口,壁紙窗口和Toast之流,由系統(tǒng)創(chuàng)建的,不依賴于父窗口。
Window:每個App雖然都可以做得各不相同,但是作為有大量用戶交互的系統(tǒng),窗口之間必須要有統(tǒng)一的交互模式,這樣才能減小用戶的學習成本。這些共性比如title, action bar的顯示和通用按鍵的處理等等。Window類就抽象了這些共性。另外,它定義了一組Callback,Activity通過實現(xiàn)這些Callback被調(diào)用來處理事件。注意要和在WMS中的窗口區(qū)分開來,WMS中的窗口更像是App端的View。
PhoneWindow:PhoneWindow是Window類的唯一實現(xiàn),至少目前是。這樣的設計下如果要加其它平臺的Window類型更加方便。每個Activity會有一個PhoneWindow,在attach到ActivityThread時創(chuàng)建,保存在mWindow成員中。
Context:運行上下文,Activity和Service本質(zhì)上都是一個Context,Context包含了它們作為運行實體的共性,如啟動Activity,綁定Service,處理Broadcast和Receiver等等。注意Application也會有Context。Activity的Context是對應Activity的,Activity被殺掉(比如轉(zhuǎn)屏后)后就變了。所以要注意如果有生命周期很長的對象有對Activity的Context的引用的話,轉(zhuǎn)屏、返回這種會引起Activity銷毀的操作都會引起內(nèi)存泄露。而Application的Context生命周期是和App進程一致的。關于Context的類結(jié)構圖有下面的形式。Context是抽象類,定義了接口。ContextImpl是Context的實現(xiàn)類,包含了實現(xiàn)。而ContextWrapper是Context的包裝類,它把請求delegate給其中的ContextImpl類去完成。ContextThemeWrapper是ContextWrapper的裝飾類,它在ContextWrapper的基礎上提供了自定義的主題。這結(jié)構初看有點亂,但結(jié)合下面的Decorator模式(java的設計模式)就一目了然了。
Surface:這是在App端管理圖形緩沖區(qū)的類,其中最重要的是圖形緩沖區(qū)隊列。經(jīng)由WMS從SF中得到IGraphicBufferProducer接口對象BufferQueue后,Surface便可以從該隊列中queue和dequeue圖形緩沖區(qū)。SurfaceControl在WMS中封裝了Surface以及與SF的交互。Canvas和Surface從字面意思上很像,但前者其實更確切地說不是“畫布”,而是“畫家”。Surface中的圖形緩沖區(qū)才是App的畫布。
1.3結(jié)構流程分析
從結(jié)構上分析,應用啟動大體可以分為3塊:
1.ams啟動的調(diào)用(見圖一)
2.應用本身生命周期的調(diào)用(見圖二)
3.Wms畫圖的調(diào)用(見圖三)
簡單的ams第一部分調(diào)用關系概括為:

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開始,主要為應用創(chuàng)建各種對象信息,方便調(diào)用,比如ActivityInfo,ActivityRecord,Stack,TaskRecord對象,檢查調(diào)用者權限,檢查intent的合法性,為intent找到相應的應用,把原activity暫停放入后臺task列表中,并且把ApplicationToken加入到wms的task隊列里面。通知wms創(chuàng)建白色的過渡window,方法為mWindowManager.setAppStartingWindow。
第二部分應用生命周期的調(diào)用,主要從ActvityThread的handleLaunchActivity開始。
新啟動的Activity的創(chuàng)建初始化主要是在handleLaunchActivity()中完成的。handleLaunchActivity()的作用是加載指定的Activity并運行。這其中在App端主要是創(chuàng)建ActivityThread,Activity,PhoneWindow,DecorView等對象,并調(diào)用Activity生命周期中的onCreate(),onResume()函數(shù)執(zhí)行用戶邏輯。正常點的App里onCreate里會調(diào)用setContentView設置主視圖。setContentView()里主要是調(diào)用了installDecor(),其中會設置窗口的通用元素,如title, action bar之類,還會把xml文件inflate成布局對象。
簡單的調(diào)用關系概括為:
handleLaunchActivity
->performLaunchActivity
?->mInstrumentation.newActivity
-> activity.attach
->mInstrumentation.callActivityOnCreate?
?->activity.onCreate
-> activity.performStart()
->handleResumeActivity
->wm.addView(decor, l);

可以看到這時創(chuàng)建了DecorView,這便是Activity的主窗口的頂層視圖。DecorView創(chuàng)建好后,handleResumeActivity()中會將它添加到WMS中去。當App向WMS添加窗口時,會調(diào)用WindowManagerImpl的addView()。注意WindowManagerImpl中的addView()函數(shù)和ViewGroup里的addView()函數(shù)完全不一樣,后者是將View加入到本地的View組織架構中去,和WMS沒有關系。
第三部分主要從addView()的流程如下:
首先通過WindowManagerImpl的addView()會創(chuàng)建對應的ViewRootImpl,然后ViewRootImpl申請WMS得到Session(如果是App第一個Activity會新建),其接口為IWindowSession,然后ViewRootImpl通過addToDisplay()把自己的ViewRootImpl::W(實現(xiàn)了IWindow接口)注冊給WMS。addView()的工作主要包括創(chuàng)建ViewRootImpl,和遠程WMS建立Session,并將當前視圖注冊到WMS這幾步??梢钥吹紸pp端通過WindowManagerGlobal調(diào)用addView(),調(diào)用鏈到WMS就變成addWindow(),概念發(fā)生了改變,這也印證上面提到的App端和WMS端的Window概念不一樣的說法。

2.Process流程
2.1進程啟動
進程的啟動的入口函數(shù)是AMS.startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags,String hostingType, ComponentName hostingName, boolean allowWhileBooting,boolean isolated, boolean keepIfLarge)。在前面的文章中知道,當啟動Activity、Service、getContentProvider時如果目標進程未啟動,那么就需要調(diào)用startProcessLocked()來啟動目標進程。所有線程啟動都是通過這里啟動,包括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")來啟動ActivityThread的線程,并在等待PROC_START_TIMEOUT時間后,查看線程時候啟動超時。
2.start函數(shù)直接調(diào)用Process.startViaZygote()-->zygoteSendArgsAndGetResult(),進程是從Zygote中孵化出來的。
3.Zygote是向socket服務端寫數(shù)據(jù),把創(chuàng)建進程的請求通過socket通訊方式來讓framework的進程孵化類zygote創(chuàng)建新進程。而數(shù)據(jù)就是argsForZygote——一個以字符串List形式的把Process.start()所有調(diào)用參數(shù)都包含在里面的變量。
socket服務端收到創(chuàng)建新進程的請求,ZygoteConnection.runOnce()接收到新進程的參數(shù),然后調(diào)用Zygote.forkAndSpecialize()來fork一個子進程,在子進程中會接著關閉socket,調(diào)用ZygoteInit.invokeStaticMain(cloader, className, mainArgs),即調(diào)用ActivityThread.main()。新的應用進程會從ActivityThread的main()函數(shù)處開始執(zhí)行。
2.1.2?ActivityThread.main()
startProcessLocked方法后面就調(diào)用了ActivityThread.main,啟動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ù)主要做一些新進程起來后的工作,比如設置ProcessRecord信息、獲取ContentProvider信息返回給ActivityThread、啟動該進程的Activity、Service、BroadCast等工作(四大組件相關),下面是詳細分析。
1.在調(diào)用startProcessLocked()啟動進程時,便將ProcessRecord和Pid加入mPidsSelfLocked中,故此時app不為null。
2.啟動應用所包含的ContentProvider,相當于將ContentProvider注冊到AMS中來,然后再把返回的參數(shù)providers傳給ActivityThread,ActivityThread根據(jù)參數(shù)加載對應的ContentProvider到應用進程中來,應用進程加載ContentProvider完成后會調(diào)用AMS.publishContentProviders()將ContentProvider信息公開。(如果應用包含有provider的信息,被oom強制殺死時會自動重啟線程)
3.保證應用的dex,只有在特殊的運行“沒有預先dexopt”模式才有作用。
4.AMS側(cè)對該進程進行一些初始化操作后邊將一些必要信息傳給ActivityThread,這個步驟對應用非常重要,應用很多初始化的數(shù)據(jù)都在這里生成,包括初始化時區(qū),設置資源,density,dpi,cache目錄信息,虛擬器大小等。
5.進程起來后,調(diào)用ActivityStackSupervisor.attachApplicationLocked來啟動相應Activity。如果未啟動的Activity要跑在當前啟動的進程中,那么直接調(diào)用realStartActivityLocked()來啟動當前,realStartActivityLocked就是啟動Activity的真正函數(shù)。
6.進程起來后調(diào)用ActiveServices.attachApplicationLocked()啟動相應服務,尋找要在當前進程中啟動的Activity,并啟動之。mPendingServices中保存著等待該進程啟動的Service,現(xiàn)在進程已經(jīng)啟動了,所以mPendingServices中保存的服務也可以啟動了,即在下面調(diào)用realStartServiceLocked()來啟動服務。
7.處理廣播,將原本要發(fā)到當前進程的廣播處理掉,調(diào)用isPendingBroadcastProcessLocked()來判斷當前啟動的進程是否是PendingBroadcast等待的進程,如果是就把PendingBroadcast廣播發(fā)送給當前這個進程中去。