Android6.0 SystemUI啟動簡析及圖標顯示刷新。Android系統的SystemUI包含狀態欄、導航欄、快捷設置、通知欄及鎖屏界面等等;主要流程是從SystemUIService的開始的。
首先在SystemServer.java中啟動SystemUIService服務;

執行到SystemUIService的onCreate()方法:

調用SystemUIApplication的startServicesIfNeeded()方法;

而在startServicesIfNeeded()此方法中會依次start相關的SystemUi類型的子類對象;
其中的SERVICES[]數組為:

以SystemBar為例:

啟動SystemBars後,在其內部的start()方法會去檢測是否存在有自定義的barservice;如果沒有的話
會回調onNoService()方法,繼而調用createStatusBarFromConfig()方法;

在此方法中的R.string.config_statusBarComponent===>
com.android.systemui.statusbar.phone.PhoneStatusBar
即此方法實質上是用來加載並啟動PhoneStatusBar的;

PhoneStatusBar的start()方法又會去調用其父類BaseStatuBar的start()方法;
在BaseStatuBar的start()方法抽象方法createAndAddWindows(),而這個抽象方法是在BaseStatuBar的子類實現,例如在PhoneStatusBar中內部被實現,即實質上調用createAndAddWindows()方法。往下分析,同樣的addIcon()方法也是如此;

調用PhoneStatusBar的createAndAddWindows()方法,調用addStatusBarWindow,繼續往下調用makeStatusBarView()方法;

此方法主要作用就是構造statusBar的view,一步步往下分析:

定義StatusBarWindowView並未其設置觸摸事件;
接下來的代碼就是用來定義狀態欄、導航欄、通知欄、鎖屏區域、下拉擴展欄、快捷設置區域等等
而在PhoneStatusBar中也實現了addIcon()方法,用來實現Icon圖標的加載;
執行完BaseStatuBar的start()方法之後,回到PhoneStatusBar的start()方法中,發現可以使用PhoneStatusBarPolicy來控制圖標Icon;

PhoneStatusBarPolicy的構造方法

分析發現此構造方法主要是用來注冊廣播監聽各種狀態,如鈴聲、SIM卡等等狀態來更新Icon的顯示圖形,最後通過調用
mService.setIcon()方法來設置顯示出來;
mService是StatusBarManager的實現對象,通過aidl調用到StatusBarManagerService.java的方法setIcon()中,往下繼續
使用StatusBarIconList.java的setIcon方法設置。而StatusBarIconList實質上一個數組集合,來對StatusBarIcon進行管理。
在android系統啟動中,StatusBarManagerService是由SystemServer注冊的

而在StatusBarManagerService的構造方法中,初始時是從config.xml中讀取Iconsolt的;

隨著Android系統啟動的不同層次,SystemUi也在不斷啟動,StatusBar也在不斷加載啟動。在BaseStatuBar中的start()方法
中,獲取StatusBarManagerService對象,創建StatusBarIconList和CommandQueue的對象並將其傳入StatusBarManagerService中;在StatusBarManagerService中通過mBar(即傳入的CommandQueue對象)進行一系列的命令操作。

CommandQueue,顧名思義是一個消息隊列,用來接收來自於StatusBarManagerService的命令,而在CommandQueue中又通過發送msg到主線程中去使用callback回調執行相應的接口。
以StatusBarManagerService中的setIcon()方法為例:

調用mBar的setIcon()方法,即為CommandQueue.java的setIcon()方法

發送msg為OP_SET_ICON的消息通知主線程Handler執行

CallBack回調addIcon()或者updateIcon();
而CommandQueue中的CallBack最終是由PhoneStatusBar來實現的,故最終的實現是由PhoneStatusBar來實現的。
圖標顯示刷新流程總結:
1、Android系統啟動時,在SystemServer中會去注冊StatusBarManagerService;
2、在StatusBarManagerService中的構造方法會去config.xml中讀取Iconslot,並在StatusBarIconList集合中構造出相應長度的StatusBarIcon[]數組和將形參slot[]賦值給mSlots[];
3、隨著Android系統的啟動,StatusBar不斷加載;通過調用BaseStatuBar的start()方法,去完成StatusBar的界面顯示和初始圖標的設置;
4、BaseStatuBar的start()主要是通過兩個方法createAndAddWindows()和addIcon()方法來完成界面顯示和初始圖標設置,而這兩個方法的主要實現是在其子類PhoneStatusBar.java中實現的;
5、BaseStatuBar的start()會獲取StatusBarManagerService對象,創建StatusBarIconList和CommandQueue的對象並將其傳入到StatusBarManagerService中;在StatusBarManagerService中通過mBar(即傳入的CommandQueue對象)進行一系列的命令操作;
6、執行完BaseStatuBar的start()方法後,即回到PhoneStatusBar的start()方法中,在這個start()方法中會去構造一個PhoneStatusBarPolicy對象;主要是用來注冊廣播監聽各種狀態,如鈴聲、SIM卡等等狀態變化來更新Icon的顯示圖形,最後通過調用
mService.setIcon()方法來設置顯示出來;
7、而mService實質上是StatusBarManagerService的aidl調用,調用到StatusBarManagerService.java中的setIcon()方法;
8、在此方法中又會調用mBar.setIcon()方法去設置圖標,而在前面我們知道mBar實質上值得是CommandQueue.java的對象,即調入CommandQueue.java中的setIcon()方法;此方法通過發送msg為OP_SET_ICON的消息通知主線程Handler執行,接下來通過Callback.addIcon()進行回調執行;
9、在CommandQueue.java的CallBack接口最終由PhoneStatusBar實現,即最終實現Icon的是在PhoneStatusBar.java的addIcon()方法內;
10、在addIcon()方法內調用mIconController.addSystemIcon()方法進入StatusBarIconController.java中的addSystemIcon()中執行。
至此完成StatusBar的顯示更新。