Android Framework 之 SystemUI的启动流程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/yichen97/article/details/90614214

前面先说一下

本文以Android O(8.0)代码为例。主要介绍从SystemService.java到启动SystemUI的过程,至于SystemUI的其他方面放至其他地方说啦。

本文所涉及的类

/frameworks/base/services/java/com/android/server/SystemServer.java

/frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java

/frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java

前面的启动过程

系统的启动过程是从 init进程 -> Zygote进程 -> SystemServer进程。

话说init进程是怎么启动的呢?

听说是按下电源键之后,系统上电,从固定地址开始加载固化在ROM的Bootloader代码在RAM中并执行,Bootloader引导程序负责将OS拉起;OS被拉起,并完成一系列初始化和系统的初始化,首先在系统文件中寻找init文件并启动用户空间第一个进程。

时序图

具体分析

0. 从代码中可以清晰的看出只做了一件事,就是调用了SystemService的 run() 方法,下面来看一下run()方法里都是运行了哪些东西。

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

1. 它将服务的启动分为了这几类:Bootstrap、Core、Other,而我们本文所涉及的SystemUI属于Other这一类,所以就进入了startOtherServices()这个私有方法。

    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();
        }
    }

2. 在startOtherServices()这个私有方法中,发现系统启动很非常多非常多的服务,SystemUI只是其中一个,下面是只启动SystemUI的相关代码。

    private void startOtherServices() {
    
    mActivityManagerService.systemReady(() -> {

            ...

            traceBeginAndSlog("StartSystemUI");
            try {
                startSystemUi(context, windowManagerF);
            } catch (Throwable e) {
                reportWtf("starting System UI", e);
            }
            traceEnd();
 
            ...

            }, BOOT_TIMINGS_TRACE_LOG);
    }

3. 启动SystemUI最后追到了startSystemUi(context, windowManagerF)这样一个方法,找到这个方法,SystemUI怎么启动的也就真相大白了。

至context.startServiceAsUser(),已经设置了包名类名和启动方式来对SystemUI的服务(SystemUIService)开始启动了。值得注意的是,在这个时候,系统还没有发送“ACTION_BOOT_COMPLETE”广播(开机广播),因为该广播是由AMS中的finishBooting()中来发送的。

    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();
    }

4. 每一个应用都会自己有一个默认的Application类,也可以根据自己的特殊需求重写一个,在这里呢,SystemUI的应用它自己重写了一个Application类,是伴随应用终身的,每一个apk的启动,该类是最先被初始化的类。

在SystemUIApplication这个类中,定义了两类的Services。

    /**
     * The classes of the stuff to start.
     */
    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,
    };

    /**
     * The classes of the stuff to start for each user.  This is a subset of the services listed
     * above.
     */
    private final Class<?>[] SERVICES_PER_USER = new Class[] {
            Dependency.class,
            NotificationChannels.class,
            Recents.class
    };

这些所有的类型,都是SystemUI的子类实现。

5. 这时,Application类的onCreate方法被触发了。

    @Override
    public void onCreate() {
        super.onCreate();
        // Set the application theme that is inherited by all services. Note that setting the
        // application theme in the manifest does only work for activities. Keep this in sync with
        // the theme set there.
        setTheme(R.style.systemui_theme);

        SystemUIFactory.createFromConfig(this);

        if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
            IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
            filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
            registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (mBootCompleted) return;

                    if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
                    unregisterReceiver(this);
                    mBootCompleted = true;
                    if (mServicesStarted) {
                        final int N = mServices.length;
                        for (int i = 0; i < N; i++) {
                            mServices[i].onBootCompleted();
                        }
                    }
                }
            }, filter);
        } else {
            // We don't need to startServices for sub-process that is doing some tasks.
            // (screenshots, sweetsweetdesserts or tuner ..)
            String processName = ActivityThread.currentProcessName();
            ApplicationInfo info = getApplicationInfo();
            if (processName != null && processName.startsWith(info.processName + ":")) {
                return;
            }
            // For a secondary user, boot-completed will never be called because it has already
            // been broadcasted on startup for the primary SystemUI process.  Instead, for
            // components which require the SystemUI component to be initialized per-user, we
            // start those components now for the current non-system user.
            startServicesIfNeeded(SERVICES_PER_USER);
        }
    }

在onCreate方法里,有一个广播接收器,他是接收开机广播的。

6. 执行完毕后,开始执行SystemUIService.java的onCreate()方法了,但是onCreate()中只一句话。

    @Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();

        // For debugging RescueParty
        if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
            throw new RuntimeException();
        }
    }

直接又调回到了SystemUIApplication.java中的startServicesIfNeeded()方法。

    public void startServicesIfNeeded() {
        startServicesIfNeeded(SERVICES);
    }

    /**
     * Ensures that all the Secondary user SystemUI services are running. If they are already
     * running, this is a no-op. This is needed to conditinally start all the services, as we only
     * need to have it in the main process.
     * <p>This method must only be called from the main thread.</p>
     */
    void startSecondaryUserServicesIfNeeded() {
        startServicesIfNeeded(SERVICES_PER_USER);
    }

    private void startServicesIfNeeded(Class<?>[] services) {
        if (mServicesStarted) {
            return;
        }

        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() + ".");
        final int N = services.length;
        for (int i = 0; i < N; i++) {
            Class<?> cl = services[i];
            if (DEBUG) Log.d(TAG, "loading: " + cl);
            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);
            }

            mServices[i].mContext = this;
            mServices[i].mComponents = mComponents;
            if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
            mServices[i].start();

            if (mBootCompleted) {
                mServices[i].onBootCompleted();
            }
        }
        Dependency.get(PluginManager.class).addPluginListener(
                new PluginListener<OverlayPlugin>() {
                    private ArraySet<OverlayPlugin> mOverlays;

                    @Override
                    public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
                        StatusBar statusBar = getComponent(StatusBar.class);
                        if (statusBar != null) {
                            plugin.setup(statusBar.getStatusBarWindow(),
                                    statusBar.getNavigationBarView());
                        }
                        // Lazy init.
                        if (mOverlays == null) mOverlays = new ArraySet<>();
                        if (plugin.holdStatusBarOpen()) {
                            mOverlays.add(plugin);
                            Dependency.get(StatusBarWindowManager.class).setStateListener(b ->
                                    mOverlays.forEach(o -> o.setCollapseDesired(b)));
                            Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
                                    mOverlays.size() != 0);

                        }
                    }

                    @Override
                    public void onPluginDisconnected(OverlayPlugin plugin) {
                        mOverlays.remove(plugin);
                        Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
                                mOverlays.size() != 0);
                    }
                }, OverlayPlugin.class, true /* Allow multiple plugins */);

        mServicesStarted = true;
    }

这里是拿到每个和 SystemUI 相关的类的反射,存到了 service[] 里,然后再通过反射将其转化为具体类的对象,存到了mService[i]数组里,最后对象调 start() 方法启动相关类的服务,启动完成后,回调 onBootCompleted( ) 方法。

因为mService[i] 里的值不同,调用的 start() 方法也不尽相同。

参考文献

史上最详细的Android系统SystemUI 启动过程详细解析

开机SystemServer到ActivityManagerService启动过程分析

SystemUI启动流程及主体布局介绍

https://blog.csdn.net/qq_28852011/article/details/79449631

猜你喜欢

转载自blog.csdn.net/yichen97/article/details/90614214