史上最詳細的Android系統SystemUI 啟動過程詳細解析
Android 系統 SystemUI 介紹
Android 的 SystemUI 其實就是 Android 的系統介面,它包括了介面上方的狀態列 status bar,下方的導航欄Navigation Bar,鎖屏介面 Keyguard ,電源介面 PowerUI,近期任務介面 Recent Task 等等。對於使用者而言,SystemUI 的改動是最能直觀感受到的。因此,每個 Android 版本在 SystemUI 上都有比較大的改動。而對開發者而言,理解 Android SystemUI 對優化Android系統介面,改善使用者體驗十分重要。
SystemUI 在哪
在 Andorid 系統原始碼中,package/apps下放的是系統內建的一些 app,例如 settings,camera,Phone,Message 等等。而在 Framework/base/package 下,它們也是系統的 app,SystemUI 就在此目錄下。它控制著整個Android系統的介面,但其實他也是一個 app,不同於一般的 app,它不可解除安裝也不可以被第三方應用替換。
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 方法如下:
public static void main(String[] args){
new SystemServer().run()
}
main 方法裡啟動了 run() 方法,而在 run 方法中呼叫了 startBootstrapServices() 方法和 startOtherServices() 方法,在 startOtherServices() 裡 mActivityManagerService.systemReady 建立執行緒去執行startSystemUi(context),這裡將啟動 SystemUI。具體方法如下:
這裡寫圖片描述
然後我們進入設定啟動 systemui 程式的 SystemUIService 檔案裡,該檔案在framework/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java.我們看該檔案的onCreate() 方法。方法如下:
這裡寫圖片描述
可以看到有一句 ((SystemUIApplication) getApplication()).startServicesIfNeeded(),這句很關鍵,我們再進入 startServicesIfNeeded(),看看具體是如何啟動系統服務的。該方法如下:
這裡寫圖片描述
其中有一個 for 迴圈,迴圈裡第一句就是將 service[i] 賦值給 cl, 那麼service裡存的是什麼呢?找到 service[i] 的賦值如下:
這裡寫圖片描述
看到這裡我們就明白了,這裡是拿到每個和 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() 方法:
這裡寫圖片描述
這裡呼叫了 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啟動流程圖:
這裡寫圖片描述
這裡寫圖片描述
作者:qiracle
連結:https://www.jianshu.com/p/2e0f403e5299
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。