Android原始碼學習
Android原始碼
下載
2018-2-4
直接使用清華大學的映象【注意不能使用VMware + Ubuntu + 共享資料夾的方式,主要英文共享資料夾不支援linux某些檔案】
https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/
目錄結構
2018-2-5
http://blog.csdn.net/itachi85/article/details/54695046
詳細目錄結構
http://blog.csdn.net/ieearth/article/details/64930164
編譯
從網上下載的android原始碼不包括u-boot和linux核心,需要下載對應的版本,然後在編譯。
android啟動流程
在學習啟動流程時,首先列印Android的啟動日誌,列印方法參見:Android核心開發:如何統計系統的啟動時間
先貼一張圖:
2018-2-6
Android 的底層基於 Linux Kernel,因此從啟動流程來看,先啟動 Linux Kernel,然後才啟動 Android Framework,最後進入應用程式 Launcher,也就是看到的主介面。因此可將Android的啟動流程分為下面3個階段:
第一階段:Linux核心啟動
主要參考:Android筆記 - Android啟動之Linux核心啟動
這一階段有分為三個過程:
(1)機器上電,進入Bootrom,
Bootrom 是固化在晶片中的一小段程式,主要功能是上電時完成硬體自檢,然後從固定分割槽載入 Bootloader。Bootrom 的功能相當於 PC 上的 BIOS,Bootloader 的功能相當於 PC 上的 GRUB。這個程式一般是硬體廠商做的,Android手機廠商不會修改。
(2)Bootloader初始化軟硬體環境 ,
Bootloader 是在進入 Linux Kernel 之前執行的程式。Android 採用的 Bootloader 實現方式是 Uboot。手機廠商一般會定製化Bootloader程式,這程式的主要作用是檢測硬體,載入linux kernel。
(3)啟動 Linux Kernel ,
這一階段和標準 Linux Kernel 啟動過程基本一致。Kernel 載入進記憶體後會進行自解壓。自解壓完成後,繼續進行一些平臺相關的初始化,然後開始 start_kernel 函式,它的實現程式碼位於 init/main.c 中。
以上分析基於 linux-4.4.52核心,至此,linux核心分析完畢。這裡的“/init”程序是使用者空間中的額第一個程序。
備註:我們知道,linux核心的系統有固定的流程,一般核心啟動完畢後,就是載入使用者的程式,使用者的程式一般放在某個指令碼中(好像是“/etc/init/init.rc”檔案),執行指令碼中的每一行語句,即開啟相應的程序。
以下是天嵌TQ2440的列印資訊(linux-2.6.30版本),可供參考:
由以上分析,Android的系統,應該是linux的核心啟動完成後,再啟動必要的程序,最後通過腳步檔案啟動Android的程式。
第二階段:Android Framework啟動
2018-2-7
init 程序(PID=1,使用者空間的第一個程序,也是Android系統的第一個程序)進入 main 函式後,主要完成以下四項工作。第一,在根檔案系統中建立目錄作為掛載點,然後掛載虛擬檔案系統;第二, 解析啟動指令碼檔案 init.rc;第三,根據啟動指令碼 init.rc 的解析結果開啟 Android Framework 核心服務程序;第四,監聽事件,重啟服務。
上面說的init程序(程序名為“/init”,PID=0,根目錄下的init可執行檔案),,是由android原始碼(Android-7.1版本)中的/system/core/init/init.cpp檔案編譯出來的,這個程序名為“/init”的程序會執行根目錄下的 init.*.rc 腳步(具體的執行規則,參見:Android的init過程(二):初始化語言(init.rc)解析),這個腳步是負責啟動Android framework的(見:Android筆記 - Android啟動之Android Framework啟動)。
為了學習AIL(Android初始化語言,Android Init Language,這裡簡稱為AIL),讀者可以到自己Android手機的根目錄尋找init.rc檔案,最好下載到本地以便檢視,如果有編譯好的Android原始碼,在<Android原始碼根目錄>out/target/product/generic/root目錄也可找到init.rc檔案。
第二步和第三步最重要,這個過程中會啟動系統所需功能的各種服務。主要分為本地服務和Android服務,它們都會在ServiceManager中進行註冊。
本地服務
本地服務是指執行在C++層的系統守護程序,一部分本地服務是init程序直接啟動的,它們定義在init.rc指令碼和init.<hardware>.rc中,如 ueventd、servicemanager、debuggerd、rild、mediaserver等。還有一部分本地服務,是由這些本地服務進一步建立的,如mediaserver服務會啟動AudioFlinger, MediaPlayerService, 以及 CameraService 等本地服務。我們可以通過檢視init.rc和init.<hardware>.rc檔案找出具體有哪些本地服務被init程序直接啟動了,這些檔案的位置:system/core/rootdir/
Android服務
Android服務是指執行在Dalvik虛擬機器程序中的服務,這些服務的建立過程描述如下:
init程序會執行app_process程式,建立Zygote程序,它是Android系統最重要的程序,後續所有的Android應用程式都是由它fork出來的。
Zygote程序會先fork出SystemServer程序,SystemServer程序就會啟動所有的Android核心服務。例如:Activity Manager、Window Manager、Power Manager等等服務。當所服務啟動完畢後,SystemServer會打印出”Making services ready”,然後通過Activity Manager啟動Home介面,併發送“ACTION_BOOT_COMPLETED”廣播訊息。
SystemServer程序新增的服務都屬於SystemServer程序。
Android服務是指執行在Dalvik虛擬機器程序中的服務,這些服務的建立過程描述如下:
init程序會執行app_process程式,建立Zygote程序,它是Android系統最重要的程序,所有後續的Android應用程式都是由它fork出來的。
第二, 解析啟動指令碼檔案 init.rc;
init 可執行檔案的程式碼(/system/core/init/init.cpp)的main函式中解析“/init.rc”腳步,原始碼:
int main(int argc, char** argv) {
.......
Parser& parser = Parser::GetInstance();
parser.AddSectionParser("service",std::make_unique<ServiceParser>());
parser.AddSectionParser("on", std::make_unique<ActionParser>());
parser.AddSectionParser("import", std::make_unique<ImportParser>());
parser.ParseConfig("/init.rc");
.......
}
解析 init.rc 的工作由函式 Parser 來完成。解析完成後,得到一個 service_list 連結串列和一個 action_list 連結串列。其中,service_list 連結串列用來儲存 service 的解析結果,action_list 連結串列用來儲存 action 的解析結果。如下圖所示:
為了讓 action 按照一定的順序觸發,需要對 action 在連結串列中的順序進行調整,調整後的 action 由 action_queue 連結串列來儲存。
第三,根據啟動指令碼 init.rc 的解析結果開啟 Android Framework 核心服務程序;
通過之前的初始化工作得到 action_queue 連結串列後,呼叫 execute_one_command 函式遍歷 action_queue 連結串列,並執行連結串列中 action 的 command。
在這些啟動的核心服務程序中,其中兩個最重要的核心服務程序是 zygote 程序和 servicemanager 程序。
zygote 程序是 Android 啟動後的第一個虛擬機器程序。它主要負責啟動 system_server 程序,以及所有的應用程式程序,所以也稱為孵化器程序。zygote 程序會啟動子程序 system_server,system_server 程序在 nativeInit 函式中啟動 Native 系統服務比如 SensorService,在 ServerThread 的 initAndLoop 函式中啟動 Java 系統服務比如 ActivityManagerService, PackageManagerService, ContentService 等,並將系統服務註冊進 ServiceManager。
servicemanager 程序是 Binder 程序間通訊機制的核心之一。它負責管理系統中所有的 Service 元件,提供 Service 元件的註冊服務,並且向 Client 元件提供獲取 Service 代理物件的服務。
分析 init.rc 檔案,發現執行順序為:
【zygote】程序
Android 7.0 版本的 init.rc檔案,其中 zygote 在 init.zygote64.rc 中的內容如下:
//android_source\system\core\rootdir\init.zygote64_32.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
根據 Android 初始化語言的語法,可以知道 zygote 服務程序的名字是 zygote ,執行程式路徑為 /system/bin/app_process64,引數為 -Xzygote /system/bin --zygote --start-system-server。建立一個名字為 zygote 的 socket,這個 socket 用於接收 ActivityManagerService 傳送過來的新建應用程式程序的請求。zygote 程序重啟時會往 sysfs 中寫入命令,同時會重啟 media 服務和 netd 服務。
Zygote程序會首先fork出"SystemServer"程序,"SystemServer"程序的全部任務就是將所有的Android核心服務啟動起來,這些服務包括:
/system/bin/app_process 是 zygote 程序的可執行程式,其原始碼位於 frameworks/base/cmds/app_process/app_main.cpp 檔案,入口函式是 main。具體啟動細節請參考老羅的文章 Android 系統程序 Zygote 啟動過程的原始碼分析。
init.*.rc 腳步依次啟動ServiceManager, Zygote, ActivityManagerService 和 PackageManagerService 等系統服務已經啟動起來,
其中,android7.1.1版本的ServiceManager對應的啟動指令碼是/system/etc/init/servicemanager.rc
第三階段:應用程式 Launcher啟動
也就是最終會看到的 Android 桌面的啟動。
http://blog.csdn.net/yanshazi/article/details/50287479