史上最詳細的Android系統SystemUI 啓動過程詳細解析

Android 系統 SystemUI 介紹

Android 的 SystemUI 其實就是 Android 的系統界面,它包括了界面上方的狀態欄 status bar,下方的導航欄Navigation Bar,鎖屏界面 Keyguard ,電源界面 PowerUI,近期任務界面 Recent Task 等等。對於用戶而言,SystemUI 的改動是最能直觀感覺到的。所以,每一個 Android 版本在 SystemUI 上都有比較大的改動。而對開發者而言,理解 Android SystemUI 對優化Android系統界面,改善用戶體驗十分重要。java

SystemUI 在哪

在 Andorid 系統源碼中,package/apps下放的是系統內置的一些 app,例如 settings,camera,Phone,Message 等等。而在 Framework/base/package 下,它們也是系統的 app,SystemUI 就在此目錄下。它控制着整個Android系統的界面,但其實他也是一個 app,不一樣於通常的 app,它不可卸載也不能夠被第三方應用替換。android

SystemUI 總體結構

這是 SystemUI 相關類的繼承關係圖,能夠看到 SystemUI 爲基類,每一個子類實現了不一樣的系統界面。數組

  • Status Bar 系統上方的狀態欄
  • Navigator Bar 系統下方的導航欄
  • Keyguard 鎖屏界面
  • PowerUI 電源界面
  • Recents Screen 近期任務界面
  • VolumeUI 音量調節對話框
  • Stack Divider 分屏功能調節器
  • PipUI 畫中畫界面
  • Screenshot 截屏界面
  • RingtonePlayer 鈴聲播放器界面
  • Settings Activity 系統設置中用到的一些界面,例如:NetworkOverLimitActivity,UsbDebuggingActivity等。

SystemUI的啓動流程

先找到 framework/base/service/java/com/android/server/SystemServer.java 文件,裏面有個main()方法,main 方法以下:app

public static void main(String[] args){
    new SystemServer().run()
}

main 方法裏啓動了 run() 方法,而在 run 方法中調用了 startBootstrapServices() 方法和 startOtherServices() 方法,在 startOtherServices() 裏 mActivityManagerService.systemReady 建立線程去執行startSystemUi(context),這裏將啓動 SystemUI。具體方法以下:ide

而後咱們進入設置啓動 systemui 程序的 SystemUIService 文件裏,該文件在framework/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java.咱們看該文件的onCreate() 方法。方法以下:佈局

能夠看到有一句 ((SystemUIApplication) getApplication()).startServicesIfNeeded(),這句很關鍵,咱們再進入 startServicesIfNeeded(),看看具體是如何啓動系統服務的。該方法以下:優化

其中有一個 for 循環,循環裏第一句就是將 service[i] 賦值給 cl, 那麼service裏存的是什麼呢?找到 service[i] 的賦值以下:ui

看到這裏咱們就明白了,這裏是拿到每一個和 SystemUI 相關的類的反射,存到了 service[] 裏,而後賦值給cl,緊接着將經過反射將其轉化爲具體類的對象,存到了mService[i]數組裏,最後對象調 start() 方法啓動相關類的服務,啓動完成後,回調 onBootCompleted( ) 方法。
mService[i] 裏的值不一樣時,調用的 start() 方法也不相同,這裏咱們以S ystemBars 的 start() 爲例,因此mService[i].start() 先認爲是 SystemBars.start().
SystemBars.java 位於framework/base/packages/SystemUI/res/com/android/systemui/statusbar/SystemBars.java ,找到 start() 方法:spa

這裏調用了 mServiceMonitor.start(),旁邊註釋說的很清楚若是服務沒有啓動的話就調用onNoService()方法,進入 onNoService() 方法,該方法就位於 start() 方法下方,能夠看到方法中調用了CreateStatusBarFromConfig() 該方法以下:線程

從中能夠知道,該方法中先讀取 value/config.xml 文件中 config_statusBarComponent 的值,這裏爲:com.android.systemui.statusbar.phone.PhoneStatusBar,而後經過反射獲得了 PhoneStatusBar 對象,最後的 mStartus.start() 也就等於 PhoneStatusBar.start(),進入該方法,會發現,裏面調用了super.start(),也就是先執行了父類的 start() ,其父類爲 BaseStatusBar,該類的star()方法較多,就不放出來了,咱們看重點,找到裏面有調用一個 createAndAddWindows(),該方法爲抽象方法,則會調用它的子類的方法,這裏也就是 PhoneStatusBar 的 createAndAddWindows()方法,以下:

createAndAddWindows() 裏只調用了 addStaBarWindow() 方法,而在該方法裏,調用了makeStartusBarView,看名字就知道該方法關鍵,意爲構建statusBar視圖。該方法很長,裏面有inflateStatusBarWindow(),進入該方法,能夠看到,這麼一句:

而後,咱們經過 super_status_bar.xml 的分析 SystemBars 的大體視圖構成了,super_status_bar.xml 代碼以下:

super_status_bar.xml
super_status_bar.xml 中 include 了一個名稱爲 status_bar 的佈局文件
super_status_bar.xml*中 include 了一個名稱爲 status_bar_expanded 的佈局文件
這裏的 status_bar 即是系統狀態欄的佈局文件,status_bar_expanded 即是下拉的通知窗口的佈局文件
上述 super_status_bar.xml 與以下視圖對應:

PhoneStatusBarView 即爲手機最上方的狀態欄,主要用於顯示系統狀態,通知等,主要包括 notification icons 和 status bar icons。status_bar.xml 即對應狀態欄的視圖以下:

PanelHolder
PanelHolder是用戶下拉 status bar 後獲得的 view。它主要包含 QuickSettings 和 Notification panel 兩個部分。
PanelHolder是一個繼承自 FrameLayout的自定義 view,它的內容是經過 include status_bar_expanded.xml進行填充的。
PanelHolder的佈局比較複雜,爲了提升 view 的重用性大量的使用了 include 標籤。
status_bar_expanded.xml 對應的視圖:

KeyguardBouncer
KeyguardBouncer是鎖屏解鎖界面,根據用戶設置的解鎖方式不一樣,展現不一樣的解鎖模式。
keyguard_bouncer.xml 對應的 KerguardBouncer 視圖:

附:
SystemUI啓動流程圖: