1. 程式人生 > >Android原始碼學習

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的init過程詳解(一)

 

第二階段: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