• Android 9.0系统源码_SystemUI(一)SystemUI的启动流程


    一、SystemUI 介绍

    1、初步认识SystemUI

    Android 的 SystemUI 其实就是 Android 的系统界面,它包括了界面上方的状态栏 status bar,下方的导航栏Navigation Bar,锁屏界面 Keyguard ,电源界面 PowerUI,近期任务界面 Recent Task 等等。对于用户而言,SystemUI 的改动是最能直观感受到的。因此,每个 Android 版本在 SystemUI 上都有比较大的改动。而对开发者而言,理解 Android SystemUI 对优化Android系统界面,改善用户体验十分重要。

    2、SystemUI 在哪

    在 Andorid 系统源码中,package/apps下放的是系统内置的一些 app,例如 settings,camera,Phone,Message 等等。而在 framework/base/package 下,它们也是系统的 app,SystemUI 就在此目录下。它控制着整个Android系统的界面,但其实他也是一个 app,不同于一般的 app,它不可卸载也不可以被第三方应用替换。因为SystemUI 是系统应用,所以它也是一个 APK,有入口 Application,只不过它是由 SystemServer 进程进行启动的。

    3、SystemUI 整体结构

    在这里插入图片描述
    这是 SystemUI 相关类的继承关系图,可以看到 SystemUI 为基类,每个子类实现了不同的系统界面。

    Status Bar 系统上方的状态栏
    Navigator Bar 系统下方的导航栏
    Keyguard 锁屏界面
    PowerUI 电源界面
    Recents Screen 近期任务界面
    VolumeUI 音量调节对话框
    Stack Divider 分屏功能调节器
    PipUI 画中画界面
    Screenshot 截屏界面
    RingtonePlayer 铃声播放器界面
    Settings Activity 系统设置中用到的一些界面,例如:NetworkOverLimitActivity,UsbDebuggingActivity等。
    在这里插入图片描述

    二、系统启动后在SystemServer进程中启动SystemUIService

    1、SystemServer进程里面有个main()方法,main 方法如下:

    framework/base/service/java/com/android/server/SystemServer.java

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

    2、main 方法里启动了 run() 方法,而在 run 方法中调用了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();
            }
        	...
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3、在 startOtherServices() 里 mActivityManagerService.systemReady 创建线程去执行startSystemUi(context),这里将启动SystemUI。具体方法如下:

        private void startOtherServices() {
                mActivityManagerService.systemReady(() -> {
              		...
    	          	try {
    	                startSystemUi(context, windowManagerF);
    	            } catch (Throwable e) {
    	                reportWtf("starting System UI", e);
    	            }
              		...  
              }
        }
        //启动SystemUI
        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();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    三、在 SystemUIService 中启动 SystemUI 所需的各种组件

    1、然后我们进入设置启动 systemui 程序的 SystemUIService 文件里,该类的onCreate() 方法如下:

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

    public class SystemUIService extends Service {
    
        @Override
        public void onCreate() {
            super.onCreate();
            ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2、((SystemUIApplication) getApplication()).startServicesIfNeeded()这句很关键,该方法如下:

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

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

    3、SystemUI要启动的所有组件都是在数组 config_systemUIServiceComponents中定义的,可以看下这个数组的定义:

    frameworks/base/packages/SystemUI/res/values/config.xml

      
        <string-array name="config_systemUIServiceComponents" translatable="false">
            <item>com.android.systemui.Dependencyitem>
            <item>com.android.systemui.util.NotificationChannelsitem>
            <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStartitem>
            <item>com.android.systemui.keyguard.KeyguardViewMediatoritem>
            <item>com.android.systemui.recents.Recentsitem>
            <item>com.android.systemui.volume.VolumeUIitem>
            <item>com.android.systemui.stackdivider.Divideritem>
            <item>com.android.systemui.SystemBarsitem>
            <item>com.android.systemui.usb.StorageNotificationitem>
            <item>com.android.systemui.power.PowerUIitem>
            <item>com.android.systemui.media.RingtonePlayeritem>
            <item>com.android.systemui.keyboard.KeyboardUIitem>
            <item>com.android.systemui.pip.PipUIitem>
            <item>com.android.systemui.shortcut.ShortcutKeyDispatcheritem>
            <item>@string/config_systemUIVendorServiceComponentitem>
            <item>com.android.systemui.util.leak.GarbageMonitor$Serviceitem>
            <item>com.android.systemui.LatencyTesteritem>
            <item>com.android.systemui.globalactions.GlobalActionsComponentitem>
            <item>com.android.systemui.ScreenDecorationsitem>
            <item>com.android.systemui.fingerprint.FingerprintDialogImplitem>
            <item>com.android.systemui.SliceBroadcastRelayHandleritem>
        string-array>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4、继续看SystemUIApplication的startServicesIfNeeded(String[] services)方法,其中有一个 for 循环,循环里第一句就是将 service[i] 赋值给 clsName, 而service[i]的赋值就是各个SystemUI的具体类对象路径,这里通过反射的方法,创建出来对应的SystemUI实例对象:

        private void startServicesIfNeeded(String[] services) {
     		...
            mServices = new SystemUI[services.length];
            ...
            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;
                ...
                mServices[i].start();
       			...
                ti = System.currentTimeMillis() - ti;
    			...
                if (mBootCompleted) {
                    mServices[i].onBootCompleted();
                }
            }
    		...
            mServicesStarted = true;
        }
    
    • 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

    看到这里我们应该就明白了,这里是拿到每个和 SystemUI 组件相关的类的完整路径,存到了service[] 里,然后赋值给cls,紧接着通过反射将其转化为具体的类对象,存到了mService[i]数组里,最后对象调start() 方法启动相关类的服务,启动完成后,再调用该类的onBootCompleted( ) 方法。

    至此我们已经分析完了SystemUI的启动流程,后续篇章我们将会继续通过源码来分析系统状态栏、导航栏等各种常见的SystemUI组件的启动流程。

  • 相关阅读:
    C选择结构程序设计
    基于现代深度学习的目标检测方法综述
    如何选择科技公司或者技术团队来开发软件项目呢
    数字化时代,数据仓库究竟是干什么的?
    echart 仪表盘实现指针的渐变色及添加图片
    微服务项目:尚融宝(1)(项目介绍)
    js正则表达式之中文验证(转)
    0034【Edabit ★☆☆☆☆☆】【修改Bug4】Buggy Code (Part 4)
    Mysql基础(二)——查询语句(select)
    基于JavaSSH框架的网上商城设计与实现
  • 原文地址:https://blog.csdn.net/abc6368765/article/details/126262764