這裏寫自定義目錄標題
簡單介紹framework在Android系統的位置
1 Android架構圖
Android架構分爲四層
- Application
- Application Framework
- Library Android Runtime
- Linux Kernel
1 源碼的目錄結構
android源碼的結構圖
鏈接:https://blog.csdn.net/yui_hatano/article/details/89517165
- bionic android上實現的libc庫
- bootable 存放可啓動項,如recovery、bootloader等
- build android編譯系統所用到的make文件及其它工具
- cts android兼容性測試
- dalvik dalvik虛擬機
- development 與開發相關的一些東西
- device 存放需要適配的設備信息
- external 第三方庫
- frameworks framework部分**
- hardware 硬件相關代碼
- kernel kernel相關代碼
- libcore android上實現的Java基礎庫
- Makefile
- ndk
- out 編譯輸出目錄
- packages 包含系統應用、壁紙應用、內容提供者、輸入法等
- prebuilt 預編譯好的工具
- sdk sdk相關內容
- system 操作系統層次的一些可執行程序和配置文件
- u-boot 用於引導linux啓動的u-boot
- vendor 存放與廠商相關的信息,也可粗放需要適配的設備信息
android framework的結構圖
應用程序框架層,這一層爲上層應用提供各種api,提供各種組件和服務來支持我們的Android開發。
framework開發相關的代碼主要集中在framework/base下面。
- frameworks/av 多媒體框架
- frameworks/base
- api/ 全是xml文件,定義了api
- cmds/ android中重要的命令,如am,app_proce
- config/ 10-Aug-2018 4 KiB
- core/ 核心庫
- java/ java庫
- jni/ jni層
- proto/ 協議層
- res/ 資源文件
- tests/ 測試工具
- data/ 聲音字體等數據文件
- docs/ 文檔
- drm/ 數字版權管理
- graphics/ 圖形圖像
- keystore/ 數字簽名證書相關
- libs/ 庫
- androidfw/ FW功能庫
- common_time/ 常用功能和工具集合
- hwui/ 硬件渲染庫
- incident/ 事件驅動機制庫
- input/ 輸入庫
- protoutil/ (7.0有,5.0沒有)
- services/ 服務庫
- storage/ 存儲庫
- usb/ USB庫
- location/ 地理位置
- lowpan/ (7.0有,5.0沒有)
- media/ 多媒體
- native/ 本地庫
- nfc-extras/ nfc相關
- obex/ 藍牙傳輸
- opengl/ opengl相關
- packages/ 設置,TTS,VPN程序
- proto/ 協議框架
- rs/ 資源框架
- samples/ 示例
- sax/ xml解析器
- services/ Android的服務
- telecomm/ telecom通訊框架
- telephony/ 電話相關
- test-base/ base的測試
- test-legacy/ 安全相關的測試
- test-mock/ (7.0有,5.0沒有)
- test-runner/ 測試相關
- tests/ 測試相關
- tools/ 工具
- vr/ VR相關(7.0有,5.0沒有)
- wifi/ 無線網絡
3 源碼中的framework重要類
下面是一些系統中常見的類及其功能介紹,通讀一遍會對理解Android源碼很有幫助。
分類 | 重要的類 | 簡介 | 作用 |
---|---|---|---|
消息處理類(非服務端) | KeyQ類 | 該類是WmS的內部類,繼承自KeyInputQueue | 一旦創建就立即啓動一個線程,該線程會不斷讀取用戶UI操作消息,比如按鍵、觸摸屏、等,並把這些消息放到一個消息隊列QueueEvent類中 |
消息處理類(非服務端) | InputDispatcherThread | 該類是WmS的內部類,繼承自KeyInputQueue | 一旦創建就立即啓動一個線程,該線程會不斷讀取用戶UI操作消息,比如按鍵、觸摸屏、等,並把這些消息放到一個消息隊列QueueEvent類中 |
服務端 | ActivityManagerService | 內存管理,進程管理,統一調度所有應用程序中的Activity | 所有Activity的啓動必須通知AmS,AmS也決定了某個進程會不會被殺死。 |
服務端 | WindowManagerService | 管理所有的窗口 | 包括創建刪除窗口,隱藏顯示窗口,決定窗口的層級順序,指定當前正在與應用程序交互的窗口。 |
客戶端 | ActivityThread | 主線程類 即UI線程類 | 所有的處理用戶消息,以及繪製頁面的工作都在該線程中完成。 |
客戶端 | Activity | apk運行的最小單位 | ActivityThread會根據用戶的操作選擇讓哪個Activity對象上它的船。 |
客戶端 | Window | 富一代,長得比較抽象,喜歡制定規則 | 提供了一些通用的窗口操作API。 |
客戶端 | PhoneWindow | 富二代,繼承於牛氣的Window類,自己屋裏住着一個DecorView對象 | 像它老爸喜歡制定規則提供了一些通用窗口操作API。 |
客戶端 | DecorView | 很能幹的傢伙,家產來自FrameLayout,比較注重外在喜歡打扮 | 對FrameLayout進行了一些修飾 |
客戶端 | ViewRoot類 | 小管家。繼承於Handler | 主要作用是把WMS的IPC調用轉換爲本地的一個異步調用。內部還有 ViewRootHandler 繼承於Handler,所以當W類收到消息以後可以發送給UI線程,界面的繪製發起點也在此。 |
客戶端 | W類 | ViewRoot小助手,繼承於binder,是ViewRoot內部類。 | 主要幫助ViewRoot實現把WMS的IPC調用轉換爲本地的一個異步調用。 |
客戶端 | WindowsManager | 客戶端與WMS的中介 | 客戶端如果想創建一個窗口得先告訴WindowManager一聲,然後它再和WindowManagerService交流一下看看能不能創建,客戶端不能直接和WMS交互 |
4 Android framework形象化理解之:三個小夥伴
Android framework包含三個小夥伴:服務端、客戶端、linux驅動。
服務端
(1)ActivityManagerService(Ams):內存管理,進程管理,統一調度所有應用程序中的Activity。所有Activity的啓動必須通知AmS,AmS也決定了某個進程會不會被殺死。
(2)WindowManagerService(Wms):管理所有的窗口,包括創建刪除窗口,隱藏顯示窗口,決定窗口的層級順序,指定當前正在與應用程序交互的窗口。
客戶端
(1)ActivityThread類 主線程類 即UI線程類,所有的處理用戶消息,以及繪製頁面的工作都在該線程中完成。
(2)Activity類,apk運行的最小單位,ActivityThread會根據用戶的操作選擇讓哪個Activity對象上它的船。
(3)Window:富一代,長得比較抽象,喜歡制定規則,提供了一些通用的窗口操作API。
(4)PhoneWindow類 :富二代,繼承於牛氣的Window類,自己屋裏住着一個DecorView對象,像它老爸喜歡制定規則提供了一些通用窗口操作API。
(5)DecorView:很能幹的傢伙,家產來自FrameLayout,比較注重外在喜歡打扮,DecorView是對FrameLayout進行了一些修飾,從名字就可以看出來。
(6)ViewRoot類 :小管家。繼承於Handler,主要作用是把WMS的IPC調用轉換爲本地的一個異步調用。內部還有 ViewRootHandler 繼承於Handler,所以當W類收到消息以後可以發送給UI線程,界面的繪製發起點也在此。
(7)W類:ViewRoot小助手,繼承於binder,是ViewRoot內部類。主要幫助ViewRoot實現把WMS的IPC調用轉換爲本地的一個異步調用。
(8)WindowsManager :客戶端如果想創建一個窗口得先告訴WindowManager一聲,然後它再和WindowManagerService交流一下看看能不能創建,客戶端不能直接和WMS交互。
Linux驅動
Linux驅動和Framework相關的主要是兩個部分:畫家SurfaceFlingger和快遞員Binder。
每一個窗口都對應一個畫Surface,SurfaceFlingger負責將各個畫面顯示到屏幕上,Binder負責進程間通信。
5 Framework啓動分析
6 應用程序啓動分析
在計算機的世界裏每個程序都有一個main()方法,程序代碼都是從main()方法開始執行,Android應用程序也不例外。
- 當應用程序啓動時,系統首先會爲其創建一個Dalvik虛擬機進程,並加載APK應用程序類及資源。
- 然後APK應用程序從ActivityThred的main()方法處開始執行。
首先,main()方法爲UI線程創建一個消息隊列(MessageQueue)。
然後,創建ActivityThread對象,ActivityThread初始化時會創建一個Handler和一個Binder。(Binder負責接收遠程AmS的IPC調用,接收到調用後通過Handler將消息發送到消息隊列,UI主線程會異步地從消息隊列中取出消息並執行相應操作,比如start,stop,pause等)
接着,UI主線程調用Looper.loop()方法進入消息循環體,進入後就會不斷從消息隊列中讀取並處理消息。( ActivityThread是APK程序的UI線程,也就是我們所說的主線程。主線程要求執行時間不能超過5秒,超過就會報ANR,這個5秒就是UI線程消息隊列循環一次的最大時間閾值) - 當ActivityThread接收到AmS發送的start某個Activity消息後,就會創建指定Activity對象。Activity又會創建PhoneWindow類,PhoneWindow創建DecorView,DecorView內部包含Activity.setContentView(R.layout.xxx)指定的佈局。
- 創建完成後,Activity需要將佈局顯示在屏幕上,於是調用WindowManager.addView()方法。WindowManager爲Activity對應的窗口(Window)創建一個ViewRoot對象(每一個窗口對應一個ViewRoot對象),然後調用WmS提供的遠程接口將窗口(佈局)顯示到屏幕上。至此應用程序中的Activity就顯示在屏幕上了。
APK中的線程
在現在操作系統中,任何應用程序都運行在線程之中。客戶端在啓動時系統會首先爲其分配一個線程,然後該線程從程序的入口處開始執行。對於包含Activity的客戶端程序,至少包含三個線程:
- 主線程,又稱UI線程,也就是應用程序本身所在的線程,主要用於處理用戶消息以及繪製程序界面。
- ViewRoot.W對象對應的線程,Activity啓動後會創建一個ViewRoot.W對象,W對象繼承自Binder,因此會啓動一個對象負責接收Linux Binder驅動的IPC調用。
- ApplicationThread對象所對應的線程,該對象也繼承自Binder,因此也會啓動一個線程用於IPC調用。
自定義Thread與UI線程的區別
客戶端小夥伴至少包含三個線程小弟,Activity啓動後會創建一個ViewRoot.W對象,同時ActivityThread會創建一個ApplicationThread對象,這兩個對象繼承消息總管Binder,每個Binder對應一個線程,負責接收Linux Binder驅動發送的IPC調用。還有一個是UI線程唄。
對於UI線程,在啓動時已經創建了消息隊列(MessageQueue),既在ActivityThread的main()方法中已經使用Looper.prepareMainLooper()方法爲UI線程添加了Looper對象。程序員可以直接在Activity中定義Handler對象發送處理消息。
而對於普通線程,需要手動調用Looper.prepareLooper()方法爲Thread創建消息隊列,這樣才能定義Handler處理消息。即不能直接在Thread中定義Handler。
從使用場景上說,就是不能直接給Thread對象發消息,但是卻可以給UI線程發消息。
UI線程是從ActivityThread運行的,在該類的main()方法中已經使用了Looper.prepareMainLooper()爲該線程添加了Looper對象,已經爲該線程創建了消息隊列,是自帶祕書光環的。因此,我們纔可以在Activity中去定義Handler對象,因爲創建Handler對象時其線程必須已經創建了消息隊列,裝卸工得配運輸帶要不然沒法幹活。而普通的Thread則沒有默認創建消息隊列,所以不能直接在Thread中直接定義Handler,這個就是我們不懂程序運行原理導致的困惑。
7 從apk程序的運行過程,去看看三個小夥伴的工作
1 ActivityThread從main()函數中就開始動起來,然後調用prepareMainLooper()爲UI線程創建一個消息快遞通道即MessageQueue。
2 接着創建ActivityThread對象,創建過程會創建一個消息裝卸工Handler對象和一個快遞員Binder對象。其中Binder負責接收遠程Ams的IPC調用,接收到調用後讓Handler把消息裝到消息快遞隊列,UI線程很忙的都是異步的從消息快遞隊列中取出消息並執行相應操作,比如 start、stop、pause。
3 UI線程讓隊列調用Looper.loop()方法進入消息循環體,進入後就會不斷地從消息隊列中讀取並處理消息。
4 當ActivityThread接收到Ams發送start某個Activity的快遞後就會創建指定的Activity對象。Activity會先按窗戶再去按玻璃和貼窗花,所以先創建PhoneWindow->DecorView->創建相應的View或ViewGroup。創建完成後就可以讓大家欣賞了,調用WindowManager把界面顯示到屏幕上,然後創建ViewRoot,然後調用Wms提供的遠程接口添加一個窗口並顯示到屏幕上。
5 接下來就是用戶的操作,事件線程不斷的把消息快遞發到事件隊列中去,然後事件分發線程祕書逐個取出消息,然後調用Wms中的相應函數處理該消息。
8 Framework 的學習方法彙總
可參考:https://blog.csdn.net/mybook1122/article/details/102805635
先注意以下幾點
1 Android系統採用C/S架構;
2 絕大部分IPC通信採用Binder通信;
3 核心Service大多運行在System_server進程;
4 核心Service代碼大部分都在frameworks/base/services目錄下;
5 別一上來就看Binder!!!
6 別一開始看源碼就鑽牛角尖!!!