本文用于記錄Android系統(tǒng)相關(guān)知識(shí)點(diǎn)。主要是文字總結(jié)~
一、Android系統(tǒng)架構(gòu)
Android系統(tǒng)架構(gòu)分為五層:
① 應(yīng)用層(APP)
② 應(yīng)用框架層(Framework)
③系統(tǒng)運(yùn)行庫(kù)層(native C/C++,比如OpenGL ES;Android runtime以及Android基礎(chǔ)庫(kù))
④ 硬件抽象層(內(nèi)核與硬件電路之間的接口層)
⑤ Linux內(nèi)核層(內(nèi)存管理,進(jìn)程管理)
二、Android系統(tǒng)啟動(dòng)
① init進(jìn)程
init進(jìn)程是Android系統(tǒng)中用戶空間的第一個(gè)進(jìn)程,被賦予了很多重要的職責(zé),比如創(chuàng)建Zygote和屬性服務(wù)等。
介紹init之前,先了解系統(tǒng)的啟動(dòng):
- 當(dāng)電源按下時(shí)引導(dǎo)芯片代碼從預(yù)定的地方(固化在ROM)開(kāi)始執(zhí)行。加載引導(dǎo)程序BootLoader到RAM中,然后執(zhí)行。BootLoader是Android系統(tǒng)運(yùn)行前的一個(gè)小程序,負(fù)責(zé)把系統(tǒng)OS拉起來(lái)并運(yùn)行。
- 當(dāng)內(nèi)核啟動(dòng)時(shí),設(shè)置緩存,被保護(hù)存儲(chǔ)器,計(jì)劃列表,加載驅(qū)動(dòng)。在內(nèi)核完成系統(tǒng)設(shè)置后,會(huì)在系統(tǒng)文件中尋找init.rc文件,并啟動(dòng)init進(jìn)程。
- init進(jìn)程用來(lái)初始化和啟動(dòng)屬性服務(wù),也用來(lái)啟動(dòng)Zygote進(jìn)程。
簡(jiǎn)單說(shuō)就是,順序就是:
引導(dǎo)程序 ?????? Linux內(nèi)核 ?????? init進(jìn)程
從init進(jìn)程的main函數(shù)可以看出,它主要是做了以下三件事:
- 創(chuàng)建和掛在啟動(dòng)所需的文件目錄
- 初始化和啟動(dòng)屬性服務(wù)。(屬性服務(wù)類(lèi)似注冊(cè)表管理器,用鍵值對(duì)記錄用戶和軟件的一些使用信息,在系統(tǒng)或軟件重啟時(shí),能根據(jù)這些記錄,進(jìn)行相應(yīng)的初始化)
- 解析init.rc 配置文件并啟動(dòng)Zygote進(jìn)程。
② Zygote進(jìn)程
Zygote之所以叫孵化器,是因?yàn)镈VM和ART,應(yīng)用程序進(jìn)程以及運(yùn)行系統(tǒng)的關(guān)鍵服務(wù)的SystemServer進(jìn)程都是由Zygote進(jìn)程所創(chuàng)建的。
Zygote進(jìn)程在啟動(dòng)時(shí)會(huì)創(chuàng)建DVM或者ART,通過(guò)fork而創(chuàng)建的APP進(jìn)程以及SystemServer進(jìn)程可以在內(nèi)部獲取一個(gè)DVM或者ART的實(shí)例副本。
在init.rc(使用的是Android Init Language)中決定要啟動(dòng)哪一個(gè)Zygote腳本(使用的是Android Init Language)。
init啟動(dòng)Zygote,會(huì)找到要啟動(dòng)的Zygote腳本,判斷進(jìn)程是否啟動(dòng),如果沒(méi)有就fork函數(shù)創(chuàng)建子進(jìn)程,并返回pid值。如果進(jìn)程被啟動(dòng),就會(huì)進(jìn)入Zygote的main函數(shù),也就是app_main.cpp的main函數(shù)中,并調(diào)用runtime的start函數(shù)啟動(dòng)ZygoteInit。
Zygote進(jìn)程都是通過(guò)fork創(chuàng)建子進(jìn)程,所以它們都可以進(jìn)入app_main.cpp的main函數(shù)。main函數(shù)的參數(shù)可以判斷該進(jìn)程是什么進(jìn)程(是Zygote還是SystemServer還是其他)。
如果是Zygote進(jìn)程,會(huì)調(diào)用AppRuntime的start函數(shù)。該函數(shù)會(huì)先創(chuàng)建java虛擬機(jī),為虛擬機(jī)注冊(cè)JNI方法。通過(guò)參數(shù)(ZygoteInit的名字)找到ZygoteInit的main方法,并通過(guò)JNI調(diào)用該main的方法。也就是這里從Native層進(jìn)入Java框架層。
ZygoteInit的main函數(shù)主要做了四件事:
- ZygoteServer創(chuàng)建一個(gè)Server端的Scoket(ScoketName為zygote,用來(lái)等待AMS請(qǐng)求Zygote進(jìn)程賚 創(chuàng)建新的應(yīng)用程序進(jìn)程)
- 預(yù)加載類(lèi)和資源
- 啟動(dòng)SystemServer進(jìn)程(Zygote通過(guò)fork,進(jìn)程名為system_server)
- 等待AMS請(qǐng)求創(chuàng)建新的應(yīng)用程序進(jìn)程(ZygoteServer的runSelectLoop,無(wú)限循環(huán)等待AMS的請(qǐng)求)
所以從上面來(lái)看,程序運(yùn)行的順序如下:
app_main ?????? AndroidRuntime ?????? ZygoteInit ?????? ZygoteServer
Zygote進(jìn)程啟動(dòng)總結(jié):
- 創(chuàng)建AppRuntime并調(diào)用其start方法,啟動(dòng)Zygote進(jìn)程。
- 創(chuàng)建java虛擬機(jī)并為java虛擬機(jī)注冊(cè)JNI方法。
- 通過(guò)JINI調(diào)用ZygoteInit的main函數(shù)進(jìn)入Zygote的java框架層。
- 通過(guò)registerZygoteSocket方法創(chuàng)建服務(wù)器端Scoket,并通過(guò)runSelectLoop方法等待AMS的請(qǐng)求來(lái)創(chuàng)建新的應(yīng)用程序。
- 啟動(dòng)SystemServer進(jìn)程。
③ SystemServer進(jìn)程
SystemServer進(jìn)程用于創(chuàng)建系統(tǒng)服務(wù)(AMS,WMS和PMS等)。
SystemServer是在ZygoteInit的startSystemServer方法中啟動(dòng)的,SystemServer進(jìn)程是Zygote的fork,需要關(guān)閉對(duì)其進(jìn)程沒(méi)用的Socket。
除了startSystemServer還要執(zhí)行handleSystemServerProcess,即處理SystemServer進(jìn)程,主要的處理呢有啟動(dòng)Binder線程池(nativeZygoteInit)和進(jìn)入SystemServer的main方法。
ZygoteInit ?????? SystemServer
nativeZygoteInit是一個(gè)JNI方法,底層是AppRuntime的onZygoteInit。onZygoteInit主要是啟動(dòng)線程池。
進(jìn)入SystemServer是通過(guò)RuntimeInit的applicationInit,接著調(diào)用invokeStaticMain,通過(guò)反射得到SystemServer類(lèi),找到SystemServer類(lèi)的main方法,通過(guò)Zygote中的靜態(tài)類(lèi)MethodAndArgsCaller動(dòng)態(tài)調(diào)用(這個(gè)有點(diǎn)不理解?)。
接下來(lái)就直行道SystemServer的main函數(shù),main函數(shù)主要有以下作用:
- 創(chuàng)建消息Looper
- 加載動(dòng)態(tài)庫(kù)
- 創(chuàng)建SystemServiceManager(會(huì)對(duì)系統(tǒng)服務(wù)進(jìn)行創(chuàng)建、啟動(dòng)和生命周期管理)
- 啟動(dòng)服務(wù)(引導(dǎo)服務(wù)、核心服務(wù)、其他服務(wù)),啟動(dòng)比較簡(jiǎn)單,直接通過(guò)
startServer,并添加在mServices中。
所以,SystemServer的啟動(dòng)流程主要經(jīng)過(guò)了以下的過(guò)程:
Zygote ?????? AndroidRuntime ?????? RuntimeInit ?????? MethodAndArgsCaller ?????? systemServer
SystemServer的主要工作:
- 啟動(dòng)Binder線程池,這樣就可以與其他進(jìn)程進(jìn)行通信。
- 創(chuàng)建SystemServiceManager,用于對(duì)系統(tǒng)服務(wù)的創(chuàng)建、啟動(dòng)和生命周期管理
- 啟動(dòng)各種系統(tǒng)服務(wù)
④ Launcher進(jìn)程
Launcher是Android系統(tǒng)的桌面,也是一個(gè)應(yīng)用程序,用來(lái)啟動(dòng)應(yīng)用程序和管理應(yīng)用程序的圖標(biāo)。Launcher在啟動(dòng)過(guò)程中會(huì)請(qǐng)求PMS返回安裝的應(yīng)用程序的信息,從而才能展示。
SystemService進(jìn)程啟動(dòng)過(guò)程中會(huì)啟動(dòng)PMS,PMS啟動(dòng)后會(huì)將系統(tǒng)中的應(yīng)用程序安裝完成。然后已經(jīng)啟動(dòng)的AMS會(huì)把Launcher啟動(dòng)起來(lái)。
在SystemServer的startOtherServices中,AMS會(huì)調(diào)用systemReady。systemReady里面
ActivityStackSupervisor(監(jiān)督者)去resumeXXX,底層是讓ActivityStack去resumeXXX,饒了一圈,最終會(huì)調(diào)用AMS的startHomeActivityLocked。
其中的調(diào)用流程如下圖:
SystemServer ?????? AMS ?????? ActivityStackSupervisor ?????? ActivityStack
?????? ActivityStackSupervisor ?????? AMS
AMS的startHomeActivityLocked是最終啟動(dòng)的關(guān)鍵,創(chuàng)建了Launcher啟動(dòng)所需的Intent,Launcher是一個(gè)程序,所以有對(duì)應(yīng)的AndroidManifest.xml,通過(guò)AndroidManifest.xml的action和category可以有符合的應(yīng)用程序已經(jīng)啟動(dòng),沒(méi)有的話調(diào)用ActivityStarterde startHomeActivityLocked來(lái)啟動(dòng)Launcher。在 startHomeActivityLocked``中,會(huì)啟動(dòng)Launcher,并進(jìn)入Launcher的onCreate```。
Launcher啟動(dòng)后還會(huì)做很多工作,比如顯示應(yīng)用程序圖標(biāo)。這些都是在onCreate中完成。
那應(yīng)用程序圖標(biāo)是怎么顯示的呢?
在onCreate中,主要涉及到以下這些類(lèi):
Launcher ?????? LauncherAppState ?????? LauncherModel
最終會(huì)在LauncherModel的startLoader里面創(chuàng)建具有消息循環(huán)的線程HandlerThread對(duì)象,創(chuàng)建Handler,傳入HandlerThread的Looper。也就需要子線程來(lái)處理某個(gè)任務(wù),這個(gè)任務(wù)就是LauncherModel的內(nèi)部類(lèi)LoaderTask,LoaderTask主要用來(lái)加載工作區(qū)信息和綁定工作區(qū)信息(Launcher是用工作區(qū)的形式來(lái)顯示系統(tǒng)安裝的應(yīng)用程序的圖標(biāo)的),以及加載系統(tǒng)已經(jīng)安裝的應(yīng)用程序信息loadAllApps,但是loadAllApps是用了mHandler的post方法,所以加載app信息這塊實(shí)際上跳到主線程去執(zhí)行,loadAllApps實(shí)際上又調(diào)用了Launcher的bindAllApplications,而bindAllApplications其實(shí)就是設(shè)置UI(mAppView)。mAppView是一個(gè)AllAppsContainerView,將app信息數(shù)組傳遞給mAppView的setApps方法,mAppView在其onFinishInflate利用recycleView實(shí)現(xiàn)app信息的展示。
這樣圖標(biāo)的顯示流程就結(jié)束了。
⑤ APP進(jìn)程
要啟動(dòng)APP,AMS要先檢查APP所需的APP進(jìn)程是否存在,不存在就會(huì)請(qǐng)求Zygote進(jìn)程啟動(dòng)需要的APP進(jìn)程。Zygote創(chuàng)建的Scoket就是用來(lái)等待AMS請(qǐng)求Zygote來(lái)創(chuàng)建新的APP進(jìn)程。Zygote進(jìn)程通過(guò)Fork自身創(chuàng)建APP進(jìn)程,APP進(jìn)程就會(huì)獲得Zygote在啟動(dòng)時(shí)創(chuàng)建的虛擬機(jī)實(shí)例,也創(chuàng)建了Binder線程池和消息循環(huán)。
所以,APP進(jìn)程的啟動(dòng)通過(guò)分割可以分為兩個(gè)步驟:
- AMS發(fā)送啟動(dòng)APP進(jìn)程請(qǐng)求
- Zygote接受請(qǐng)求并創(chuàng)建APP進(jìn)程
AMS發(fā)送啟動(dòng)APP進(jìn)程請(qǐng)求
AMS通過(guò)調(diào)用startProcessLocked方法向Zygote進(jìn)程發(fā)送請(qǐng)求。在startProcessLocked主要處理數(shù)據(jù)(用戶ID,線程名等),然后調(diào)用Process(線程類(lèi))的start,又跳轉(zhuǎn)到ZygoteProcess的start→startViaZygote,在startViaZygote中,會(huì)講應(yīng)用進(jìn)程的啟動(dòng)參數(shù)保存在argsForZygote中,方法的最后會(huì)調(diào)用zygoteSendArgsAndGetResult。zygoteSendArgsAndGetResult需要兩個(gè)參數(shù)ZygoteState和argsForZygote,ZygoteState是ZygoteProcessopenZygoteSocketIfNeeded返回的,在openZygoteSocketIfNeeded中,與Zygote進(jìn)程建立Scoket連接,并返回ZygoteState。這邊有點(diǎn)繞,ZygoteProcess不是Zygote進(jìn)程的角色,是用來(lái)保持與Zygote進(jìn)程的通信狀態(tài),ZygoteState是ZygoteProcess的靜態(tài)內(nèi)部類(lèi),用來(lái)表示與Zygote進(jìn)程通信的狀態(tài)。
走到這步,ZygoteProcess與Zygote進(jìn)程算是連接成功了,zygoteSendArgsAndGetResult會(huì)將argsForZygote寫(xiě)入到ZygoteState,Zygote進(jìn)程會(huì)通過(guò)ZygoteState收到一個(gè)創(chuàng)建新的APP進(jìn)程的請(qǐng)求。
所以,大概的流程如下:
AMS ?????? Process ?????? ZygoteProcess ?????? ZygoteState
ZygoteState是一個(gè)最終的橋梁。
Zygote接受請(qǐng)求并創(chuàng)建APP進(jìn)程
在之前講到的中,ZygoteInit的main中,zygoteServer會(huì)創(chuàng)建Scoket,runSelectLoop來(lái)等待AMS請(qǐng)求。那runSelectLoop又做了哪些事?runSelectLoop開(kāi)啟了一個(gè)死循環(huán),用來(lái)等待ZygoteConnection的runOnce執(zhí)行,```runOnce``做了以下的事情
- 獲取應(yīng)用程序進(jìn)程的啟動(dòng)參數(shù)
- 封裝成新的參數(shù)
- 創(chuàng)建應(yīng)用程序進(jìn)程
- 關(guān)閉Socket(不需要Socket)
- 處理應(yīng)用程序進(jìn)程(ZygoteInit的
zygoteInit)
其他幾條好理解,處理應(yīng)用程序進(jìn)程是執(zhí)行ZygoteInit的zygoteInit,又讓RuntimeInit和ZygoteInit做了一些事,概括起來(lái)就是創(chuàng)建Binder線程池,通過(guò)反射獲取到ActivityThread類(lèi)和main方法,最終執(zhí)行其main方法,至此就是完成APP進(jìn)程的創(chuàng)建并運(yùn)行了主線程的管理類(lèi)ActivityThread。
大概的流程如下:
Zygote ?????? ZygoteServer ?????? ZygoteConnection ?????? RuntimeInit ?????? ActivityThread
還有一個(gè)需要補(bǔ)充的點(diǎn), Binder線程池的啟動(dòng)過(guò)程
Binder線程池的啟動(dòng)在ZygoteInit的zygoteInit方法中,是調(diào)用ZygoteInit的nativeZygoteInit,這是一個(gè)JNI方法,對(duì)應(yīng)的CPP實(shí)現(xiàn)是AndroidRuntime的方法,AppRuntime繼承自AndroidRuntime,最終又是調(diào)用AppRuntime的onZygoteInit(實(shí)現(xiàn)在app_main.cpp),通過(guò)ProcessState的startThreadPool來(lái)啟動(dòng)Binder線程池。
支持Binder通信的進(jìn)程中都有一個(gè)ProcessState類(lèi),其中有個(gè)mThreadPoolStarted屬性來(lái)保證被啟動(dòng)一次。沒(méi)有啟動(dòng)的情況會(huì)調(diào)用spawnPooledThread來(lái)創(chuàng)建線程池的第一個(gè)線程,也就是線程池的主線程。
Binder線程是PoolThread類(lèi)型(繼承Thread),在創(chuàng)建的時(shí)候會(huì)將當(dāng)前線程注冊(cè)到Binder驅(qū)動(dòng)程序中,這樣該線程也加入了Binder線程池中,新創(chuàng)建的APP進(jìn)程也就支持Binder進(jìn)程間通信了。
我們只需創(chuàng)建當(dāng)前進(jìn)程的Binder對(duì)象,并將它注冊(cè)到ServiceManager中就可以實(shí)現(xiàn)Binder進(jìn)程間通信,而不必關(guān)心進(jìn)程間是如何通過(guò)Binder進(jìn)行通信的。