Framework簡介

簡單介紹framework在Android系統的位置

1 Android架構圖

在這裏插入圖片描述
Android架構分爲四層

  1. Application
  2. Application Framework
  3. Library Android Runtime
  4. 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啓動分析

zygote(SocSystemServer(ActivityManapp創建創建你,幫我管理SocketClient請求開啓新的進程啓動appapp要啓動創建新的android虛擬機,啓動appzygote(SocSystemServer(ActivityManapp

6 應用程序啓動分析

在計算機的世界裏每個程序都有一個main()方法,程序代碼都是從main()方法開始執行,Android應用程序也不例外。

  1. 當應用程序啓動時,系統首先會爲其創建一個Dalvik虛擬機進程,並加載APK應用程序類及資源。
  2. 然後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線程消息隊列循環一次的最大時間閾值)
  3. 當ActivityThread接收到AmS發送的start某個Activity消息後,就會創建指定Activity對象。Activity又會創建PhoneWindow類,PhoneWindow創建DecorView,DecorView內部包含Activity.setContentView(R.layout.xxx)指定的佈局。
  4. 創建完成後,Activity需要將佈局顯示在屏幕上,於是調用WindowManager.addView()方法。WindowManager爲Activity對應的窗口(Window)創建一個ViewRoot對象(每一個窗口對應一個ViewRoot對象),然後調用WmS提供的遠程接口將窗口(佈局)顯示到屏幕上。至此應用程序中的Activity就顯示在屏幕上了。

APK中的線程

  在現在操作系統中,任何應用程序都運行在線程之中。客戶端在啓動時系統會首先爲其分配一個線程,然後該線程從程序的入口處開始執行。對於包含Activity的客戶端程序,至少包含三個線程:
  1. 主線程,又稱UI線程,也就是應用程序本身所在的線程,主要用於處理用戶消息以及繪製程序界面。
  2. ViewRoot.W對象對應的線程,Activity啓動後會創建一個ViewRoot.W對象,W對象繼承自Binder,因此會啓動一個對象負責接收Linux Binder驅動的IPC調用。
  3. 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 別一開始看源碼就鑽牛角尖!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章