通過兩年的時間,終於完成對Android系統的研究了。Android是一個博大精深的系統,老羅不敢說本身精通了(事實上最討厭的就是說本身精 通神馬 神馬的了,或者說企業說要招聘精通神馬神馬的人才),可是至少能夠說打通了整個Android系統,從最上面的應用層,一直到最下面的Linux內核,煉 就的是一種內功修養。這篇文章和你們一塊兒分享這兩年研究Android系統的歷程,以此感謝你們一直以來的支持和鼓勵。 如下是本文的提綱:html
1. 理念android
2. 里程碑程序員
3. 看過的書網絡
4. 研究過的內容架構
5. 未來要作的事情框架
它們涵蓋了老羅這兩年一直想要和你們分享的內容。好了,不說廢話了,直入主題。ide
一. 理念oop
這裏說的理念是說應該帶什麼樣的心態去研究一個系統。古人說書中自的顏如玉,書中自有黃金屋,我想說代碼裏也有顏如玉和黃金屋,因此老羅但願你們都能 「Read The Fucking Source Code」。再者,對於優秀的開源項目來講,不去讀一下它的源代碼,簡直就是暴殄天物啊。那麼,讀代碼有什麼好處呢?太多了,除了能夠學到別人的優秀代 碼、架構以外,最重要的是,咱們能從中找到答案,從而能夠解決本身項目上的燃眉之急。佈局
咱們在項目中碰到問題的時候,一般第一反應都是到網上去搜索答案。可是有時候有些問題,網絡並不能給出滿意的答案。這時候就千萬不要忘了你所擁有的一個大 招——從代碼中找答案!固然,從代碼中找答案提及來是輕鬆,可是等到直正去找時,可能就會發現雲裏霧裏,根本不知道那些代碼在說什麼東東,甚至連本身想要 看的源代碼文件都不知道在哪裏。這就要求平時就要養成讀代碼的習慣,不要臨時抱佛腳。有時候臨時抱佛腳是能解決問題,可是千萬不能抱着這種僥倖內心,掌握 一門技術仍是須要踏踏實實地一步一步走。學習
胡克其實在牛頓以前,就發現了萬有引力定律,而且推導出了正確的公式。但因爲數學很差,他只能勉強解釋行星繞日的圓周運動,而沒有認識到支配天體運行的力 量是「萬有」的。後來數學狂人牛頓用微積分圓滿地解決了胡克的問題,而且把他提出的力學三條基本定律推廣到了星系空間,改變了自從亞里士多德以來公認的天 地不一的舊觀點,被科學界奉爲偉大的發現。胡克大怒,指責牛頓剽竊了他的成果。牛頓尖酸刻薄的回敬:是啊,我他媽還真是站在巨人的肩膀上呢!
咱們有理由相信像牛頓、喬布斯之類的狂人,不用站在巨人的肩膀上也能取得矚目的成就。可是,咱們不是牛頓,也不是喬布斯,因此在看代碼以前,仍是找一些前 人總結的資料來看看吧。拿Android系統來講,你在至少得懂點Linux內核基礎吧!因此在看Android源代碼以前,先找些Linux內核的經典 書籍來看看吧,騷年!後面老羅會推薦一些書籍給你們。
另外,咱們知道,如今的互聯網產品,講究的是快速迭代。Android系統自第一個版本發佈以來,到如今已經經歷了不少版本呢?那麼咱們應該如何去選擇版 原本閱讀呢?通常來講,就是選擇最新的版原本閱讀了。不過隨着又有新版本的源代碼的發佈,咱們所看的源代碼就會變成舊版本。這時候內心就會比較糾結:是應 該繼續看舊的代碼,仍是去追新版本的代碼呢?就當是看連續劇,一會兒跳到前面去,可能就不知道講什麼了。其實版本就算更新得再快,基礎的東西也是不會輕易 變化的。咱們看代碼時,要抱着的一個目的就是弄懂它的骨架和脈絡。畢竟對於一個系統來講,它是有不少細節的,咱們沒法在短期把它們都徹底吃透。可是主要 咱們掌握了它的骨架和脈絡,之後不管是要了解它的什麼細節,均可以很輕輕地找到相關的源文件,而且能夠很容易進入主題。
坦白說,對於Android系統,不少細節我也不瞭解。因此有時候大家能夠看到,在博客文章後面的評論上,有些同窗問的一些比較具體的問題,我是沒有回覆 的。一來是我不懂,二來是我也沒有時間去幫這些同窗去扒代碼來看。這也是在文章一開頭,我就說本身沒有精通Android系統的緣由。可是請相信,主要你 熟悉Android系統的代碼,而且有出現問題的現場,順藤摸瓜跟着代碼走下去,而且多一點耐心和細心,是能夠解決問題的!
關於Android版本的問題,相信你們都知道我如今的文章都是基於2.3來寫的。不少同窗都說我out了,如今都4.2了,甚至4.3或者5.0都要出 來了,還在看2.3。我想說的是,主要你掌握了它的骨架和脈絡,不管版本上怎麼變化,原理都是同樣的,這就是以不變應萬變之道。所以,我就一直堅持研究 2.3,這樣可使得前先後後研究的東西更連貫一致,避免分散了本身的精力。若是還有疑問的話,後面我講到Android的UI架構時,就會簡單對比一下 4.2和2.3的不一樣,其實就會發現,基本原理仍是同樣的!
說到Android系統的骨架和脈絡,也有同窗抱怨個人文章裏面太多代碼細節了,他們但願我能夠抽象一下,用高度歸納的語言或者圖像來勾勒出每個模塊的 輪廓。我想說的是,若是你不看代碼,不瞭解細節,即便我可以用歸納的語言或者圖像來勾勒出這樣的輪廓出來,也許這個輪廓只有我才能看得懂。
我在真正開始看Android系統的源代碼以前,也是有這樣的想法,但願能有一張圖來清楚地告訴我Android系統的輪廓,例如,HAL爲何要將驅動 劃分紅用戶空間和內核空間兩部分,爲何說Binder是全部IPC機制效率最高的。我確實是從網上獲得抽象的資料來解釋這兩個問題,可是這些資料對我來 說,仍是太抽象了,以致於我有似懂非懂的感受,實際上就是不懂!就是由於這樣,激發了我要從代碼中找答案的念頭!如今當我回過頭來這些所謂抽象的輪廓時, 我就清楚地知道它講的是什麼了。
因此古人云「天將降大任於斯人也,必先苦其心志,勞其筋骨,餓其體膚」是有道理的,由於只有親身經歷過一些磨難後獲得的東西纔是真實的!
好了,關於理念的問題,就完了,這裏再作一下總結:
1. 從代碼中找答案——Read The Fucking Source Code。
2. 以不變應萬變——堅持看一個版本的代碼直至理清它的骨架和脈絡。
二. 里程碑
研究Android 2.3期間,主要是經歷瞭如下五個時間點,如圖1所示:
圖1 研究Android 2.3的里程碑
從2011年06月21日第一篇博客文章開始,到2013年06月03日結束對Android 2.3的研究,一共是差很少兩年的時間,一個從無到有的過程。其中,最痛苦的莫過因而2011年12月下旬到2012年06月12日這6個多月的時間裏 面,整理了2011年12月下旬前的全部博客文章,造成了《Android系統源代碼情景分析》一書,而且最終在2012年10月下旬正式上市。
總的來講,就是在兩年的時間裏面,得到了如下的兩個產出:
1. 《老羅的Android之旅》博客專欄93篇文章,1857224次訪問,4156條評論,13440積分,排名154。
2. 《Android系統源代碼情景分析》一書3大篇16章,830頁,1570000字。
以上產出除了能幫助到廣大的網友以外,也讓本身理清了Android系統的骨架和脈絡。這些骨架和脈絡接下來再總結。2013年06月03日以後,將何去何從?接下來老羅也會簡單說明。
三. 看過的書
在2011年06月21日開始寫博客以前,其實已經看過很多的書。在2011年06月21日以後,也一邊寫博客一邊看過很多的書。這個書單很長,下面我主要分類列出一些主要的和經典的。
語言:
《深度探索C++對象模型》,對應的英文版是《Inside C+++ Object Model》
程序編譯、連接、加載:
《連接器和加載器》,對應的英文版是《Linker and Loader》
《程序員的自我修養:連接、裝載和庫》
操做系統:
《Linux內核設計與實現》,對應的英文版是《Linux Kernel Development》
《深刻理解Linux內核》,對應的英文版是《Understanding the Linux Kernel》
《深刻Linux內核架構》,對應的英文版是《Professional Linux Kernel Architecture》
《Linux內核源代碼情景分析》
網絡:
《Linux 網絡體系結構:Linux內核中網絡協議的設計與實現》,對應的英文版是《The Linux Networking Architecture: Design and Implementation of Network Protocols in the Linux Kernel》
《深刻理解LINUX網絡技術內幕》,對應的英文版是《 Understanding Linux Network Internals》
設備驅動:
《Linux設備驅動程序》,對應的英文版是《Linux Device Drivers》
《精通Linux設備驅動程序開發》,對應的英文版是《Essential Linux Device Drivers》
虛擬機:
《Java SE 7虛擬機規範》
《深刻Java虛擬機》,對應的英文版是《Inside the Java Virtual Machine》
《Oracle JRockit: The Definitive Guide》
嵌入式:
《嵌入式Linux開發》,對應的英文版是《Embedded Linux Primer》
《構建嵌入式Linux系統》,對應的英文版是《Building Embedded Linux Systems》
ARM體系架構:
《ARM嵌入式系統開發:軟件設計與優化》,對應的英文版是《ARM System Developer's Guide: Designing and Optimizing System Software》
綜合:
《深刻理解計算機系統》,對應的英文版是《Computer Systems: A Programmer's Perspective》
上面介紹的這些書,都是屬於進階級別的,因此要求要有必定的語言基礎以及操做系統基礎。此外,對於看書,老羅有一些觀點,供你們參考:
1. 書不是要用的時候纔去看的,要養成常常看書、終身學習的習慣。
2. 不要只看與目前本身工做相關的書,IT技術突飛猛進,三五年河東,三五年河西。
3. 書看得多了,就會越看越快,學習新的東西時也越容易進入狀態。
對於Android應用開發,力推官方文檔:
http://developer.android.com/training/index.html
http://developer.android.com/guide/components/index.html
http://developer.android.com/tools/index.html
四. 研究過的內容
整個博客的內容看似鬆散,實際上都是有組織有計劃的,目標是打通整個Android系統,從最上面的應用層,到最下面的Linux內核層。簡單來講,博客的全部文章能夠劃分爲「三橫三縱」,如圖2所示:
圖2 Android系統研究之「三橫三縱」
接下來,老羅就分別描述這三條橫線和縱線,而且給出對應的博客文章連接。
1. 準備 -- Preparation -- 橫線
主要就是:
(1)經過閱讀相關的書籍來了解Linux內核和Android應用基礎知識
(2)搭建好Android源代碼環境
在Ubuntu上下載、編譯和安裝Android最新內核源代碼(Linux Kernel)
(3)Android系統有不少C++代碼,這些C++代碼用到了不少智能指針,所以有必要了解一下Android系統在C/C++ Runtime Framework中提供的智能指針
Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析
2. 專用驅動 -- Proprietary Drivers -- 橫線
這些專用驅動就是指Logger、Binder和Ashmem,它們整個Android系統的基石:
(1)Logger
Android應用程序框架層和系統運行庫層日誌系統源代碼分析
(2)Binder
Android進程間通訊(IPC)機制Binder簡要介紹和學習計劃
淺談Service Manager成爲Android進程間通訊(IPC)機制Binder守護進程之路
淺談Android系統進程間通訊(IPC)機制Binder中的Server和Client得到Service Manager接口之路
Android系統進程間通訊(IPC)機制Binder中的Server啓動過程源代碼分析
Android系統進程間通訊(IPC)機制Binder中的Client得到Server遠程接口過程源代碼分析
Android系統進程間通訊Binder機制在應用程序框架層的Java接口源代碼分析
(3)Ashmem
Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃
Android系統匿名共享內存Ashmem(Anonymous Shared Memory)驅動程序源代碼分析
Android系統匿名共享內存Ashmem(Anonymous Shared Memory)在進程間共享的原理分析
Android系統匿名共享內存(Anonymous Shared Memory)C++調用接口分析
3. 硬件抽象層 -- HAL -- 縱線
硬件抽層象最適合用做Android系統的學習入口,它從下到上涉及到了Android系統的各個層次:
在Ubuntu上爲Android系統編寫Linux內核驅動程序
在Ubuntu上爲Android系統內置C可執行程序測試Linux內核驅動程序
在Ubuntu上爲Android增長硬件抽象層(HAL)模塊訪問Linux內核驅動程序
在Ubuntu爲Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口
在Ubuntu上爲Android系統的Application Frameworks層增長硬件訪問服務
在Ubuntu上爲Android系統內置Java應用程序測試Application Frameworks層的硬件服務
4. 應用程序組件 -- Application Component -- 縱線
應用程序組件是Android系統的核心,爲開發者提供了貼心的服務。應用程序組件有四種,分別是Activity、Service、Broadcast Receiver和Content Provider。圍繞應用程序組件,又有應用程序進程、消息循環和安裝三個相關模塊。
(1)Activity
Android應用程序的Activity啓動過程簡要介紹和學習計劃
Android應用程序內部啓動Activity過程(startActivity)的源代碼分析
Android應用程序在新的進程中啓動新的Activity的方法和過程分析
解開Android應用程序組件Activity的"singleTask"之謎
(2)Service
Android系統在新進程中啓動自定義服務過程(startService)的原理分析
Android應用程序綁定服務(bindService)的過程源代碼分析
(3)Broadcast Receiver
Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃
Android應用程序註冊廣播接收器(registerReceiver)的過程分析
Android應用程序發送廣播(sendBroadcast)的過程分析
(4)Content Provider
Android應用程序組件Content Provider簡要介紹和學習計劃
Android應用程序組件Content Provider應用實例
Android應用程序組件Content Provider的啓動過程源代碼分析
Android應用程序組件Content Provider在應用程序之間共享數據的原理分析
Android應用程序組件Content Provider的共享數據更新通知機制分析
(5)進程
(6)消息循環
Android應用程序消息處理機制(Looper、Handler)分析
Android應用程序鍵盤(Keyboard)消息處理機制分析
(7)安裝
Android系統默認Home應用程序(Launcher)的啓動過程源代碼分析
5. 用戶界面架構 -- UI -- 縱線
你們對老羅如今還在寫Android 2.3的UI架構意見最大,認爲已通過時了。老羅認爲持有這種觀點的人,都是沒有通過認真思考的。老羅認可,從Android 4.0開始,UI部分發生了比較大的變化。可是請注意,這些變化都是在Android 2.3的UI架構基礎之上進行的,也就是說,Android 2.3的UI架構並無過期。你不能說Android 4.0在Android 2.3之上增長了一些feature,就說Android 2.3過期了。
下面這張是從Android官網拿過來的最新UI渲染流程圖,也就是4.2的UI渲染流程圖:
圖2 Android 4.2的UI渲染流程
從這張圖能夠看出關於Android的UI架構的三條主線:
(1)每個Window的Surface都怎樣渲染的?無論怎麼樣,最後渲染出來的都是一個Buffer,交給SurfaceFlinger合成到Display上。
(2)SurfaceFlinger是怎樣合成每個Window的Surface的?
(3)WindowManamgerService是怎麼樣管理Window的?
第(1)和第(2)兩個點在2.3和4.2之間有變化,主要是由於增長了GPU的支持,具體就表現爲Window的Surface在渲染的時候使用了 GPU,而SurfaceFlinger在合成每個Window的Surface的時候,也使用了GPU或者Overlay和Blitter這些硬件加 速,可是主體流程都沒有變,也就是說,Window的Surface渲染好以後,最終依然是交給SurfaceFlinger來合成。此外,雖然我尚未 開始看4.2的代碼,可是能夠看得出,4.2裏面的HWComposer,只不過是封裝和抽象了2.3就有的Overlay和Blitter,而 SurfaceTexture的做用與2.3的SurfaceComposerClient、SurfaceControl也是相似的。第(3)點基本上 就沒有什麼變化,除非之後要支持多窗口。
經過上述對比,只想強調一點:Android 2.3的UI架構並無過期,是值得去研究的,而且在2.3的基礎上去研究4.2的UI架構,會更有幫助。
仁者見仁,智者見智,Android 2.3的UI架構的說明就到此爲止,接下來它的分析路線,都是圍繞上述三個點來進行的。
首先是以開機動畫爲切入點,瞭解Linux內核裏面的驅動:
FB驅動抽象了顯卡,上面的用戶空間程序就是經過它來顯示UI的。
HAL層的Gralloc模塊對FB驅動進行了封裝,以方便SurfaceFlinger對它進行訪問:
Android幀緩衝區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析
SurfaceFlinger負責合成各個應用程序窗口的UI,也就是將各個窗口的UI合成,而且經過FB顯示在屏幕上。在對SurfaceFlinger進行分析以前,咱們首先了解應用程序是如何使用的它的:
Android應用程序與SurfaceFlinger服務的關係概述和學習計劃
Android應用程序與SurfaceFlinger服務的鏈接過程分析
Android應用程序與SurfaceFlinger服務之間的共享UI元數據(SharedClient)的建立過程分析
Android應用程序請求SurfaceFlinger服務建立Surface的過程分析
Android應用程序請求SurfaceFlinger服務渲染Surface的過程分析
萬事俱備,能夠開始分析SurfaceFlinger了:
Android系統Surface機制的SurfaceFlinger服務簡要介紹和學習計劃
Android系統Surface機制的SurfaceFlinger服務的啓動過程分析
Android系統Surface機制的SurfaceFlinger服務對幀緩衝區(Frame Buffer)的管理分析
Android系統Surface機制的SurfaceFlinger服務的線程模型分析
Android系統Surface機制的SurfaceFlinger服務渲染應用程序UI的過程分析
SurfaceFlinger操做的對象是應用程序窗口,所以,咱們要掌握應用程序窗口的組成:
Android應用程序窗口(Activity)實現框架簡要介紹和學習計劃
Android應用程序窗口(Activity)的運行上下文環境(Context)的建立過程分析
Android應用程序窗口(Activity)的窗口對象(Window)的建立過程分析
Android應用程序窗口(Activity)的視圖對象(View)的建立過程分析
Android應用程序窗口(Activity)與WindowManagerService服務的鏈接過程分析
Android應用程序窗口(Activity)的繪圖表面(Surface)的建立過程分析
Android應用程序窗口(Activity)的測量(Measure)、佈局(Layout)和繪製(Draw)過程分析
應用程序窗口是由WindowManagerService進行管理的,而且也是WindowManagerService負責提供窗口信息給SurfaceFlinger的,所以,咱們最後分析WindowManagerService:
Android窗口管理服務WindowManagerService的簡要介紹和學習計劃
Android窗口管理服務WindowManagerService計算Activity窗口大小的過程分析
Android窗口管理服務WindowManagerService對窗口的組織方式分析
Android窗口管理服務WindowManagerService對輸入法窗口(Input Method Window)的管理分析
Android窗口管理服務WindowManagerService對壁紙窗口(Wallpaper Window)的管理分析
Android窗口管理服務WindowManagerService計算窗口Z軸位置的過程分析
Android窗口管理服務WindowManagerService顯示Activity組件的啓動窗口(Starting Window)的過程分析
Android窗口管理服務WindowManagerService切換Activity窗口(App Transition)的過程分析
Android窗口管理服務WindowManagerService顯示窗口動畫的原理分析
上述內容都研究清楚以後,Android系統的UI架構的骨架就清晰了。可是前面所研究的應用程序窗口仍是太抽象了,咱們有必要研究一下那些組成應用程序窗口內容的UI控件是怎麼實現的,以TextView和SurfaceView爲表明:
最後,分析Android系統的UI架構,怎能不提它的資源管理框架?它有效地分離了代碼和UI:
Android資源管理框架(Asset Manager)簡要介紹和學習計劃
Android應用程序資源管理器(Asset Manager)的建立過程分析
分析這裏,Android系統的UI架構就分析完成了,看出什麼門道來沒有?是的,咱們以開機動畫爲切入點,從Linux內核空間的FB驅動,一直分析到 用戶空間中HAL層模塊Gralloc、C/C++ Runtime Framework層的SurfaceFlinger、Java Runtime Framework層的WindowMangerService、Window、Widget,以及資源管理框架,從下到上,披荊斬棘。
6. Dalvik虛擬機 -- 橫線
Android系統的應用程序及部分應用程序框架是使用Java語言開發的,它們運行在Dalvik虛擬機之上,還有另一部分應用唾棄框架在使用 C/C++語言開發的。使用Java語言開發的應用程序框架老羅稱之爲Java Runtime Framework,而使用C/C++語言開發的應用程序框架老羅稱之爲C/C++ Runtime Framework,它們被Dalvik虛擬機一分爲二。經過前面的學習,其實咱們都已經瞭解Android系統的Java Runtime Framework和C/C++ Runtime Framework,所以,咱們最後將注意力集中在Dalvik虛擬機上:
學習完成「三橫三縱」這六條主線以後,咱們就能夠自豪地說,從上到下地把Android系統打通,而且將它的骨架和脈絡也理清了!
對 於「準備」、「專用驅動」、「HAL」、「應用程序組件」這四條主線,老羅極力推薦你們看《Android系統源代碼狀況分析》一書,內容比博客文章要系 統、詳細不少,不說其它的,就單單是講Binder進程間通訊機制的那一章,就物超所值。在《Android系統源代碼情景分析》一書中,老羅最引覺得豪 的就是講Binder進程間通訊機制的第5章,網上或者其它書上絕對是找不到這麼詳盡的分析資料。
五. 未來要作的事情
接下來要作的主要是三件事情:
1. 繼續研究Android系統
原本覺得前段時間的Google I/O會發布Android 4.3或者5.0,而後老羅就以最新發布的版本爲藍原本進行研究。既然沒有發佈新版本,那麼就只有以如今的最新發布版本 4.2爲藍本進行研究了。如前所述,4.2與2.3相比,最大的不一樣之處是默認增長了GPU支持,所以,老羅在接下來的一段時間裏,將着重研究4.2的 GPU支持。
2. 中止博客更新
這兩年投入在博客上的精力太多了,博客上的文章基本上熬夜熬出來的。大多數時候,一個話題要花一個星期左右的時間來看代碼,而後再花四個星期左右的時間將 文章寫出來。原本是這樣計劃的,依靠《Android系統源代碼情景分析》一書的銷量,能夠在經濟上獲得必定的回報,而後能夠繼續在博客上投入,直至把 4.x版本的GPU支持寫完,最後再整理出一本關於Android系統UI架構的書。可是最近詢問了一下書的銷量,差強人意,達不到預期目標。因爲沒有形 成良性循環,所以沒有辦法,只好中止博客更新。老羅須要把精力投入在其它事情上,但願你們諒解!
3. 仍然會持續地進行一些小分享
主要是一些隨筆分享,這些分享主要會發布在微博或者QQ羣上面,那裏也方便一些和你們進行討論。此外,老羅也樂意和你們進行一些線下分享,主要針對企業或 者單位組織的沙龍、活動和會議等,同時也能夠單獨地針對企業內部進行分享。不過前提固然是舉辦方對《老羅的Android之旅》專欄或者《Android 系統源代碼情景分析》一書的內容感興趣,而且邀請老羅去參加。
若是須要邀請老羅去參加分享,能夠經過微博或者郵箱和老羅聯繫,很是感謝你們兩年以來的支持!
郵箱:shyluo@gmail.com