啓動Statusbar並顯示信號欄圖標的過程
Systemserver在啓動系統服務的時候啓動了Systemui。
try {
startSystemUi(context, windowManagerF);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
static final void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
SystemUIService
@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
}
接着使用反射的方式來啓動SystemUIFactory.
public void startServicesIfNeeded() {
startServicesIfNeeded(SERVICES);
}
這裏的SERVICES對應的是靜態數組
private final Class<?>[] SERVICES = new Class[] {
Dependency.class,
NotificationChannels.class,
CommandQueue.CommandQueueStart.class,
KeyguardViewMediator.class,
Recents.class,
VolumeUI.class,
Divider.class,
SystemBars.class, /////////////狀態欄
StorageNotification.class,
PowerUI.class,
RingtonePlayer.class,
KeyboardUI.class,
PipUI.class,
ShortcutKeyDispatcher.class,
VendorServices.class,
GarbageMonitor.Service.class,
LatencyTester.class,
GlobalActionsComponent.class,
RoundedCorners.class,
};
startServicesIfNeeded
private void startServicesIfNeeded(Class<?>[] services) {
...
for (int i = 0; i < N; i++) {
Class<?> cl = services[i];
if (DEBUG) Log.d(TAG, "loading: " + cl);
log.traceBegin("StartServices" + cl.getSimpleName());
long ti = System.currentTimeMillis();
try {
Object newService = SystemUIFactory.getInstance().createInstance(cl);
mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
}
上面的newService返回的是null,所以會去調用SERVICES的類名去初始化。
其中SystemBars就是包含了頂部狀態欄Statusbar和底部導航欄Navigationbar。
SystemBars
public class SystemBars extends SystemUI
@Override
public void start() {
if (DEBUG) Log.d(TAG, "start");
createStatusBarFromConfig();
}
private void createStatusBarFromConfig() {
if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
final String clsName = mContext.getString(R.string.config_statusBarComponent);
if (clsName == null || clsName.length() == 0) {
throw andLog("No status bar component configured", null);
}
Class<?> cls = null;
try {
cls = mContext.getClassLoader().loadClass(clsName);
} catch (Throwable t) {
throw andLog("Error loading status bar component: " + clsName, t);
}
try {
mStatusBar = (SystemUI) cls.newInstance();
} catch (Throwable t) {
throw andLog("Error creating status bar component: " + clsName, t);
}
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mComponents;
mStatusBar.start();
if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}
然後這裏也是使用反射的方式來啓動statusbar,
R.string.config_statusBarComponent對應的內容是
<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>
也就是說,到這裏纔是正式啓動StatusBar。
進入到StatusBar.start();
@Override
public void start() {
....
createAndAddWindows();
....
}
start裏做了很多其他初始化處理,但是最關鍵的是添加view和window的過程。
public void createAndAddWindows() {
addStatusBarWindow();
}
private void addStatusBarWindow() {
makeStatusBarView();
mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
mRemoteInputController = new RemoteInputController(mHeadsUpManager);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
protected void makeStatusBarView() {
final Context context = mContext;
updateDisplaySize(); // populates mDisplayMetrics
updateResources();
updateTheme();
inflateStatusBarWindow(context);
....
FragmentHostManager.get(mStatusBarWindow)
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
CollapsedStatusBarFragment statusBarFragment =
(CollapsedStatusBarFragment) fragment;
statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
mStatusBarView = (PhoneStatusBarView) fragment.getView();
mStatusBarView.setBar(this);
mStatusBarView.setPanel(mNotificationPanel);
mStatusBarView.setScrimController(mScrimController);
mStatusBarView.setBouncerShowing(mBouncerShowing);
setAreThereNotifications();
checkBarModes();
/// M: add for plmn display feature @{
attachPlmnPlugin();
///@}
}).getFragmentManager()
.beginTransaction()
.replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
CollapsedStatusBarFragment.TAG)
.commit();
....
try {
boolean showNav = mWindowManagerService.hasNavigationBar();
if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
if (showNav) {
createNavigationBar();
}
} catch (RemoteException ex) {
// no window manager? good luck with that
}
....
}
makeStatusBarView裏有也有很多view的處理流程。後面還去判斷是否啓動NavigationBar。
其中有一段是把status_bar_container啓動了一個CollapsedStatusBarFragment。
status_bar_container這個view是顯示衆多statusbar view的地方。
CollapsedStatusBarFragment
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.status_bar, container, false);
}
這裏加載了statusbar的layout
R.layout.status_bar這個layout裝載了許多的view。
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mStatusBar = (PhoneStatusBarView) view;
mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
carrierText = (CarrierText)mStatusBar.findViewById(R.id.system_carrier_text);
mSignalClusterView = mStatusBar.findViewById(R.id.signal_cluster);
// Default to showing until we know otherwise.
showSystemIconArea(false);
initEmergencyCryptkeeperText();
}
在onViewCreated裏則是幾個重要view的初始化。
分別有
mSystemIconArea用來顯示狀態欄左邊圖標的區域
carrierText用來顯示網絡供應商的名稱
mSignalClusterView則是用來顯示信號相關的信息
以上就是信號欄初始化的流程。