Android 9.0 SystemUI 啓動流程

基於 AOSP 9.0 分析。java

開機流程

開機大體會經歷以下幾個過程:android

  1. uboot 在引導 os 啓動,而後加載 kernel;
  2. 當 kernel 加載完成後,進入 init 進程,fork 出 zygote,而後由 zygote 去啓動 SystemServer;
  3. SystemServer 會啓動系統運行所需的衆多核心服務和普通服務,以及初始化和加載一些應用;
  4. 以後就進入到鎖屏或者 Launcher,開機過程就基本結束了。

SystemUI 啓動就是從 SystemServer 開始的。markdown

序列圖

SystemServer#main

SystemServer 名爲系統服務進程,負責啓動 Android 系統的關鍵服務,其入口是 SystemServer.main():ide

public static void main(String[] args) {
    new SystemServer().run();
}
複製代碼

能夠看到 main() 中生成了 SystemServer 對象並執行了 run 方法:ui

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():this

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();
}
複製代碼

經過 intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService"))啓動了服務 SystemUIService,進入 SystemUIService。spa

SystemUIService#onCreate

public class SystemUIService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        //省略其餘代碼
複製代碼

onCreate 方法中得到 SystemUIApplication 對象並調用其 startServicesIfNeeded 方法。3d

SystemUIApplication#startServicesIfNeeded

public void startServicesIfNeeded() {
    String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
    startServicesIfNeeded(names);
}
複製代碼

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

<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 方法:orm

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 啓動流程分析完畢。

更多文章能夠關注公號 「吳小龍同窗」。

相關文章
相關標籤/搜索