Android 13.0 SystemUI 启动流程

1、手机开机后,Android系统首先会创建一个Zygote(核心进程)。
2、由Zygote启动SystemServer。
3、SystemServer会启动系统运行所需的众多核心服务和普通服务、以及一些应用及数据。例如:SystemUI 启动就是从 SystemServer 里启动的。
4、进入锁屏界面,开机完成。

SystemServer 中有一个 main()方法为系统服务的入口;

/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}

在SystemServer 中的 main()方法中,就一句代码生成 SystemServer 对象,执行run 方法。在run()方法里启动了各类服务;

private void run() {
//省略部分代码
// Start services.
try {
traceBeginAndSlog(“StartServices”);
startBootstrapServices();
startCoreServices();
startOtherServices(); // 在该方法里启动了 SystemUI的服务。
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e(“System”, “******************************");
Slog.e(“System”, "
Failure starting system services”, ex);
throw ex;
} finally {
traceEnd();
}
//省略部分代码
}

private void startOtherServices() {
//省略部分代码
t.traceBegin(“StartSystemUI”);
try {
startSystemUi(context, windowManagerF);
} catch (Throwable e) {
reportWtf(“starting System UI”, e);
}
t.traceEnd();
//省略部分代码
}

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);
// 启动 SystemUIService
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
SystemServer功能图:

接着进入到 SystemUIService 的onCreate()方法里:

@Override
public void onCreate() {
    super.onCreate();

    // Start all of SystemUI
    // 调用 SystemUIApplication 的 startServicesIfNeeded() 方法。
    ((SystemUIApplication) getApplication()).startServicesIfNeeded();
   
    // 省略部分代码...
}

接着看 SystemUIApplication 的 startServicesIfNeeded() 方法。

public void startServicesIfNeeded() {
final String vendorComponent = SystemUIFactory.getInstance()
.getVendorComponent(getResources());

    // 对 startables 进行排序,以便我们获得确定性排序。
    // TODO:使 start 幂等并要求 CoreStartable 的用户调用它

   Map<Class<?>, Provider<CoreStartable>> sortedStartables = new TreeMap<>(
   Comparator.comparing(Class::getName));
   // 重点关注,这是与之前版本不一样的地方。
   sortedStartables.putAll(SystemUIFactory.getInstance().getStartableComponents());
   sortedStartables.putAll(SystemUIFactory.getInstance().getStartableComponentsPerUser());
   startServicesIfNeeded(
   sortedStartables, "StartServices", vendorComponent);

}
这里的 sortedStartables 是一个Map,里面存放待启动的各种SystemUI服务。
上述代码中 SystemUIFactory.getInstance().getStartableComponents() 我们一起来看看,如何获取的:

//SystemUIFactory.java

public class SystemUIFactory {

// 省略部分代码…
/**

* Returns the list of {@link CoreStartable} components that should be started per user.
*/
public Map<Class<?>, Provider<CoreStartable>> getStartableComponents() {
     return mSysUIComponent.getStartables();  //这里将会返回要启动的组件列表
}

// 省略部分代码…
}
接着将会进入到 SysUIComponent.java中:

@SysUISingleton
@Subcomponent(modules = {
DefaultComponentBinder.class,
DependencyProvider.class,
SystemUIBinder.class,
SystemUIModule.class,
SystemUICoreStartableModule.class,
ReferenceSystemUIModule.class})
public interface SysUIComponent {

     // 省略部分代码......
    /**
     * Returns {@link CoreStartable}s that should be started with the application.
     */
    Map<Class<?>, Provider<CoreStartable>> getStartables();

    // 省略部分代码......

}
这里使用了dagger的 @IntoMap注入相关类。只要是 继承 CoreStartable(之前版本的SystemUI) 类的都将会被注入。

注入方法,例如:

/** Inject into PowerUI. */
@Binds
@IntoMap
@ClassKey(PowerUI::class)
abstract fun bindPowerUI(sysui: PowerUI): CoreStartable
这里相关类就注入结束了,接着回到 SystemUIApplication 的 startServicesIfNeeded() 方法

private void startServicesIfNeeded(
Map<Class<?>, Provider> startables,
String metricsPrefix,
String vendorComponent) {
if (mServicesStarted) {
return;
}
mServices = new CoreStartable[startables.size() + (vendorComponent == null ? 0 : 1)];

if (!mBootCompleteCache.isBootComplete()) {
    // check to see if maybe it was already completed long before we began
    // see ActivityManagerService.finishBooting()
    if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
        mBootCompleteCache.setBootComplete();
        if (DEBUG) {
            Log.v(TAG, "BOOT_COMPLETED was already sent");
        }
    }
}

mDumpManager = mSysUIComponent.createDumpManager();

Log.v(TAG, "Starting SystemUI services for user " +
        Process.myUserHandle().getIdentifier() + ".");
TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
        Trace.TRACE_TAG_APP);
log.traceBegin(metricsPrefix);

int i = 0;
for (Map.Entry<Class<?>, Provider<CoreStartable>> entry : startables.entrySet()) {
    String clsName = entry.getKey().getName();   // 获取类名
    int j = i;  // Copied to make lambda happy.
    timeInitialization(
            clsName,
            () -> mServices[j] = startStartable(clsName, entry.getValue()),  // 跟进去会发现,这里就和之前版本一样,调用start()方法启动对应服务。
            log,
            metricsPrefix);
    i++;
}

// 省略部分代码......

log.traceEnd();

mServicesStarted = true;
FeatureOptions.sShouldShowUI = true;

}
到此 CoreStartable (SystemUI) 启动流程分析完毕。