前言
本文基于Android15源码对SystemUI启动流程及结构框架进行初步分析。
一、启动流程
启动流程主要包括以下两部分。
1.在Framework中启动SystemUIService
zygote进程启动SystemServer,在run()方法通过startOtherServices启动一系列服务,其中也包括SystemUI相关的服务,主要是在startSystemUi()方法。
frameworks/base/services/java/com/android/server/SystemServer.java
private static void startSystemUi(Context context, WindowManagerService windowManager) {
PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
Intent intent = new Intent();
intent.setComponent(pm.getSystemUiServiceComponent());
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
可以看到最终是通过PackageManagerInternal.getSystemUiServiceComponent()获取到SystemUIService组件,然后使用startServiceAsUser方法启动了服务。
2.在SystemUIService中启动SystemUI所需的各种组件
2.1 SystemUIApplication
由于SystemUI是一个app,其主入口在SystemUIApplication。
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
public void onCreate() {
...
mInitializer = mContextAvailableCallback.onContextAvailable(this);
mSysUIComponent = mInitializer.getSysUIComponent();
mBootCompleteCache = mSysUIComponent.provideBootCacheImpl();
...
if (mProcessWrapper.isSystemUser()) {
...
IntentFilter bootCompletedFilter = new
IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED);
bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
...
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mBootCompleteCache.isBootComplete()) return;
if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
unregisterReceiver(this);
mBootCompleteCache.setBootComplete();
if (mServicesStarted) {
final int N = mServices.length;
for (int i = 0; i < N; i++) {
notifyBootCompleted(mServices[i]);
}
}
}
}, bootCompletedFilter);
IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
if (!mBootCompleteCache.isBootComplete()) return;
// Update names of SystemUi notification channels
NotificationChannels.createAll(context);
}
}
}, localeChangedFilter);
} else {
...
startSecondaryUserServicesIfNeeded();
}
}
onCreate()方法主要是做一些初始化工作,如果是系统启动的服务,则进行 boot completed 等通知的注册,然后系统启动完成后,通知到各个组件,如果是在多用户环境下,则通过调用startSecondaryUserServicesIfNeeded()启动一系列的服务。
private void startServicesIfNeeded(
Map<Class<?>, Provider<CoreStartable>> startables,
String metricsPrefix,
String vendorComponent) {
if (mServicesStarted) {
return;
}
mServices = new CoreStartable[startables.size() + (vendorComponent == null ? 0 : 1)];
....
do {
startedAny = false;
queue = nextQueue;
nextQueue = new ArrayDeque<>(startables.size());
while (!queue.isEmpty()) {
Map.Entry<Class<?>, Provider<CoreStartable>> entry = queue.removeFirst();
Class<?> cls = entry.getKey();
Set<Class<? extends CoreStartable>> deps =
mSysUIComponent.getStartableDependencies().get(cls);
if (deps == null || startedStartables.containsAll(deps)) {
String clsName = cls.getName();
int i = serviceIndex; // Copied to make lambda happy.
timeInitialization(
clsName,
() -> mServices[i] = startStartable(clsName, entry.getValue()),
log,
metricsPrefix);
startedStartables.add(cls);
startedAny = true;
serviceIndex++;
} else {
nextQueue.add(entry);
}
}
numIterations++;
} while (startedAny && !nextQueue.isEmpty()); // if none were started, stop.
...
mSysUIComponent.getInitController().executePostInitTasks();
...
}
startSecondaryUserServicesIfNeeded()通过调用startServicesIfNeeded()构造了一系列服务组件CoreStartable并存在了一个mServices数组里面,执行各个组件的startStartable()方法,这样各个组件就完成了启动工作。
2.2 SystemUIService
SystemUIService是一个关键的服务, 在onCreate()的时候会通过startSystemUserServicesIfNeeded()跳转回SystemUIApplication中的startServicesIfNeeded()方法。
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
public void onCreate() {
super.onCreate();
// Start all of SystemUI
((SystemUIApplication) getApplication()).startSystemUserServicesIfNeeded();
// Finish initializing dump logic
mLogBufferFreezer.attach(mBroadcastDispatcher);
// Attempt to dump all LogBuffers for any uncaught exception
mUncaughtExceptionPreHandlerManager.registerHandler(
(thread, throwable) -> mLogBufferEulogizer.record(throwable));
// If configured, set up a battery notification
if (getResources().getBoolean(R.bool.config_showNotificationForUnknownBatteryState)) {
mBatteryStateNotifier.startListening();
}
...
}
3.启动主要流程图
二、结构框架
SystemUI的整体结构可以拆分成StatusBarWindow和NotificationShadeWindow两大部分。其中StatusBarWindow 是系统顶部的常驻状态栏容器,主要用于显示系统图标(如电池、Wi-Fi、信号强度)、时间、通知图标等,而NotificationShadeWindow 是用户下拉状态栏后展开的面板,包括完整的通知列表和快速设置等。
框架图如下: