Android 9.0 SystemUI 启动流程

基于 AOSP 9.0 分析。

开机流程

开机大致会经历如下几个过程:

  1. uboot 在引导 os 启动,然后加载 kernel;
  2. 当 kernel 加载完成后,进入 init 进程,fork 出 zygote,然后由 zygote 去启动 SystemServer;
  3. SystemServer 会启动系统运行所需的众多核心服务和普通服务,以及初始化和加载一些应用;
  4. 之后就进入到锁屏或者 Launcher,开机过程就基本结束了。

SystemUI 启动就是从 SystemServer 开始的。

序列图

SystemServer#main

SystemServer 名为系统服务进程,负责启动 Android 系统的关键服务,其入口是 SystemServer.main():

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

可以看到 main() 中生成了 SystemServer 对象并执行了 run 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void run() {
//省略部分代码
// Start services.
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
//省略部分代码
}

查看 startOtherServices():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void startOtherServices() {
//省略部分代码
traceBeginAndSlog("StartSystemUI");
try {
startSystemUi(context, windowManagerF);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
traceEnd();
//省略部分代码
}
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();
}

通过

ComponentName("com.android.systemui",
1
2
3
4
5
6
7
8
9
10
11
"com.android.systemui.SystemUIService"))```启动了服务 SystemUIService,进入 SystemUIService。
## SystemUIService#onCreate
```java
public class SystemUIService extends Service {
@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
//省略其他代码

onCreate 方法中获得 SystemUIApplication 对象并调用其 startServicesIfNeeded 方法。

SystemUIApplication#startServicesIfNeeded

1
2
3
4
public void startServicesIfNeeded() {
String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
startServicesIfNeeded(names);
}

其中 config_systemUIServiceComponents 值在 AOSP/frameworks/base/packages/SystemUI/res/values/config.xml 里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<string-array name="config_systemUIServiceComponents" translatable="false">
<!-- 对其他模块提供组件支持 -->
<item>com.android.systemui.Dependency</item>
<!-- NotificationChannel -->
<item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
<!-- 锁屏模块 -->
<item>com.android.systemui.keyguard.KeyguardViewMediator</item>
<!-- 最近应用 -->
<item>com.android.systemui.recents.Recents</item>
<!-- 全局音量控制 -->
<item>com.android.systemui.volume.VolumeUI</item>
<!-- 分屏功能调节器 -->
<item>com.android.systemui.stackdivider.Divider</item>
<!-- 系统状态栏,包括 StatusBar、NavigationBar、快捷菜单等等 -->
<item>com.android.systemui.SystemBars</item>
<!-- Storage 存储通知 -->
<item>com.android.systemui.usb.StorageNotification</item>
<!-- 电量管理相关 -->
<item>com.android.systemui.power.PowerUI</item>
<!-- 铃声播放 -->
<item>com.android.systemui.media.RingtonePlayer</item>
<!-- 键盘相关 -->
<item>com.android.systemui.keyboard.KeyboardUI</item>
<!-- 画中画界面 -->
<item>com.android.systemui.pip.PipUI</item>
<!-- 快捷键调度程序 -->
<item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
<item>@string/config_systemUIVendorServiceComponent</item>
<item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
<item>com.android.systemui.LatencyTester</item>
<item>com.android.systemui.globalactions.GlobalActionsComponent</item>
<!-- 截屏界面 -->
<item>com.android.systemui.ScreenDecorations</item>
<!-- 指纹相关 -->
<item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
<item>com.android.systemui.SliceBroadcastRelayHandler</item>
</string-array>

SystemUIApplication#startServicesIfNeeded

继续看 startServicesIfNeeded 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
private void startServicesIfNeeded(String[] services) {
if (mServicesStarted) {
return;
}
mServices = new SystemUI[services.length];
if (!mBootCompleted) {
// check to see if maybe it was already completed long before we began
// see ActivityManagerService.finishBooting()
if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
mBootCompleted = true;
if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
}
}
Log.v(TAG, "Starting SystemUI services for user " +
Process.myUserHandle().getIdentifier() + ".");
TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
Trace.TRACE_TAG_APP);
log.traceBegin("StartServices");
final int N = services.length;
for (int i = 0; i < N; i++) {
String clsName = services[i];
if (DEBUG) Log.d(TAG, "loading: " + clsName);
log.traceBegin("StartServices" + clsName);
long ti = System.currentTimeMillis();
Class cls;
try {
cls = Class.forName(clsName);
mServices[i] = (SystemUI) cls.newInstance();
} catch(ClassNotFoundException ex){
throw new RuntimeException(ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
}
mServices[i].mContext = this;
mServices[i].mComponents = mComponents;
if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
mServices[i].start();
log.traceEnd();
//省略其他代码
}
}

可以看到 startServicesIfNeeded() 循环 start 了config_systemUIServiceComponents 里的 Service,这里的 Service 都是继承了 SystemUI 类的子服务,后续将一一分析这些 Service。这样,SystemUI 启动流程分析完毕。



联系作者

我的微信公众号:吴小龙同学,欢迎关注交流,公号回复关键字「1024」有惊喜哦。