[Android14] SystemUI的启动

1. 什么是System UI

        SystemUI是Android系统级应用,负责反馈系统及应用状态并与用户保持大量的交互。业务主要涉及的组成部分包括状态栏(Status Bar),通知栏(Notification Panel),锁屏(Keyguard),控制中心(Quick Setting),音量调节(VolumeUI), 近期任务(Recents)等等。

图例如下所示:

2. 源码位置

package name:    com.android.systemui

SystemUI源码目录位于: framework/base/packages/SystemUI

Application位于:        frameworks\base\packages\SystemUI\SystemUIApplication

Service位于:            frameworks\base\services\java\com\android\server\

3. systemUI 启动流程

SystemServer.run()-> startOtherServices()-> startSystemUi()

SystemServer由ZygoteInit进程创建并启动

frameworks/base/services/java/com/android/server/SystemServer.java/*** The main entry point from zygote.*/public static void main(String[] args) {new SystemServer().run();}private void run() {......// Start services.try {t.traceBegin("StartServices");startBootstrapServices(t);startCoreServices(t);startOtherServices(t);  //在这里会启动startSystemUi()} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {t.traceEnd(); // StartServices}......}/*** Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.*/private void startOtherServices(@NonNull TimingsTraceAndSlog t) {......try {startSystemUi(context, windowManagerF);} catch (Throwable e) {reportWtf("starting System UI", e);}......}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);context.startServiceAsUser(intent, UserHandle.SYSTEM);windowManager.onSystemUiStarted();}

注意看这一段 

intent.setComponent(pm.getSystemUiServiceComponent());

pm是PackageManagerInternal实例,它的getSystemUiServiceComponent()方法是一个抽象方法

frameworks/base/services/core/java/android/content/pm/PackageManagerInternal.java/*** @return The SystemUI service component name.*/public abstract ComponentName getSystemUiServiceComponent();

PackageManagerService实现了该方法,如下:

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java@Overridepublic ComponentName getSystemUiServiceComponent() {return ComponentName.unflattenFromString(mContext.getResources().getString(com.android.internal.R.string.config_systemUIServiceComponent));}

 com.android.internal.R.string.config_systemUIServiceComponent的值是

frameworks/base/core/res/res/values/config.xml<!-- SystemUi service component --><string name="config_systemUIServiceComponent" translatable="false">com.android.systemui/com.android.systemui.SystemUIService</string>

 unflattenFromString返回的是ComponentName(“com.android.systemui”, “com.android.systemui.SystemUIService”);

unflattenFromString 具体方法如下,很简单,感兴趣的可以看看,不感兴趣的直接跳过就好,这个方法不是重点。

    /*** Recover a ComponentName from a String that was previously created with* {@link #flattenToString()}.  It splits the string at the first '/',* taking the part before as the package name and the part after as the* class name.  As a special convenience (to use, for example, when* parsing component names on the command line), if the '/' is immediately* followed by a '.' then the final class name will be the concatenation* of the package name with the string following the '/'.  Thus* "com.foo/.Blah" becomes package="com.foo" class="com.foo.Blah".** @param str The String that was returned by flattenToString().* @return Returns a new ComponentName containing the package and class* names that were encoded in <var>str</var>** @see #flattenToString()*/public static @Nullable ComponentName unflattenFromString(@NonNull String str) {int sep = str.indexOf('/');if (sep < 0 || (sep+1) >= str.length()) {return null;}String pkg = str.substring(0, sep);String cls = str.substring(sep+1);if (cls.length() > 0 && cls.charAt(0) == '.') {cls = pkg + cls;}return new ComponentName(pkg, cls);}

以上代码功能为通过Intent启动了SystemUIService。

于是走到SystemUIService的onCreate()方法

frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.javapublic void onCreate() {super.onCreate();// Start all of SystemUI((SystemUIApplication) getApplication()).startServicesIfNeeded();......}public void startServicesIfNeeded() {String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);}

通过工厂模式获得SystemUI组件列表

frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIFactory.javapublic String[] getSystemUIServiceComponents(Resources resources) {return resources.getStringArray(R.array.config_systemUIServiceComponents);}

 列表如下:

frameworks/base/packages/SystemUI/res/values/config.xml<!-- SystemUI Services: The classes of the stuff to start. --><string-array name="config_systemUIServiceComponents" translatable="false"><item>com.android.systemui.util.NotificationChannels</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><item>com.android.systemui.statusbar.phone.StatusBar</item><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.biometrics.AuthController</item><item>com.android.systemui.SliceBroadcastRelayHandler</item><item>com.android.systemui.SizeCompatModeActivityController</item><item>com.android.systemui.statusbar.notification.InstantAppNotifier</item><item>com.android.systemui.theme.ThemeOverlayController</item><item>com.android.systemui.accessibility.WindowMagnification</item><item>com.android.systemui.accessibility.SystemActions</item><item>com.android.systemui.toast.ToastUI</item></string-array>

 这个列表是要传到上面的String[] names里的,作为参数,下一步执行startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);

方法如下:

大致内容就是通过反射获得上面列表的类的构造函数,然后通过构造函数创建上面那些类的实例,然后调用这些类的start方法,启动这些systemuI组件。

private void startServicesIfNeeded(String metricsPrefix, String[] services) {if (mServicesStarted) {return;}mServices = new SystemUI[services.length];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");}}}final DumpManager dumpManager = mRootComponent.createDumpManager();Log.v(TAG, "Starting SystemUI services for user " +Process.myUserHandle().getIdentifier() + ".");TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",Trace.TRACE_TAG_APP);log.traceBegin(metricsPrefix);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(metricsPrefix + clsName);long ti = System.currentTimeMillis();try {SystemUI obj = mComponentHelper.resolveSystemUI(clsName);if (obj == null) {Constructor constructor = Class.forName(clsName).getConstructor(Context.class);  //获取构造函数obj = (SystemUI) constructor.newInstance(this); //通过构造函数获取实例}mServices[i] = obj; //把实例放入到mServices数组中} catch (ClassNotFoundException| NoSuchMethodException| IllegalAccessException| InstantiationException| InvocationTargetException ex) {throw new RuntimeException(ex);}if (DEBUG) Log.d(TAG, "running: " + mServices[i]);mServices[i].start(); //执行start方法log.traceEnd();// Warn if initialization of component takes too longti = System.currentTimeMillis() - ti;if (ti > 1000) {Log.w(TAG, "Initialization of " + clsName + " took " + ti + " ms");}if (mBootCompleteCache.isBootComplete()) {mServices[i].onBootCompleted();}dumpManager.registerDumpable(mServices[i].getClass().getName(), mServices[i]);}mRootComponent.getInitController().executePostInitTasks();log.traceEnd();mServicesStarted = true;}

SystemUI的启动就是这样。剩下的就是启动具体组件了,例如com.android.systemui.statusbar.phone.StatusBar。

StatusBar也就是状态栏,想看状态栏怎么启动的可以跟到它的start方法,这篇就先到这里。

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/3867.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

北京车展创新纷呈,移远通信网联赋能

时隔四年&#xff0c;备受瞩目的2024&#xff08;第十八届&#xff09;北京国际汽车展览会于4月25日盛大开幕。在这场汽车行业盛会上&#xff0c;各大主流车企竞相炫技&#xff0c;众多全球首发车、概念车、新能源车在这里汇聚&#xff0c;深刻揭示了汽车产业的最新成果和发展潮…

Rust中的函数指针

什么是函数指针 通过函数指针允许我们使用函数作为另一个函数的参数。函数的类型是 fn &#xff08;使用小写的 ”f” &#xff09;以免与 Fn 闭包 trait 相混淆。fn 被称为 函数指针&#xff08;function pointer&#xff09;。指定参数为函数指针的语法类似于闭包。 函数指…

前端到全栈进阶之“前端框架”

从前端入门到全栈-系列介绍 你会学到什么&#xff1f; 可能学不到什么东西&#xff0c;该系列是作者本人工作和学习积累&#xff0c;用于复习 系列介绍 现在的 Web 前端已经离不开 Node.js&#xff0c;我们广泛使用的 Babel、Webpack、工程化都是基于 Node 的&#xff0c;各…

使用Keil移植工程时修改单片机型号参数

系列文章目录 STM32单片机系列专栏 C语言术语和结构总结专栏 当使用Keil对STM32系列单片机开发时&#xff0c;如果使用的是库函数&#xff0c;那么不同型号单片机的工程项目文件是可以直接移植的。只需要按照下面的步骤修改对应的芯片&#xff0c;就可以直接将工程移植过去&a…

RabbitMQ(高级)笔记

一、生产者可靠性 &#xff08;1&#xff09;生产者重连&#xff08;不建议使用&#xff09; logging:pattern:dateformat: MM-dd HH:mm:ss:SSSspring:rabbitmq:virtual-host: /hamllport: 5672host: 192.168.92.136username: hmallpassword: 123listener:simple:prefetch: 1c…

hive启动beeline报错

问题一在zpark启动集群报错 出现上面的问题执行以下代码 chmod 777 /opt/apps/hadoop-3.2.1/logs 问题二启动beeline报错 执行 cd /opt/apps/hadoop-3.2.1 bin/hadoop dfsadmin -safemode leave 问题三执行查询语句报错 执行 set hive.exec.mode.local.autotrue;

Spring Boot Admin

概述 Spirng Boot Admin 登录页面 Spring Boot Admin是一个用于管理Spring Boot应用的监控工具,它允许你查看和管理多个Spring Boot应用实例。用于应用信息进行界面化的展示&#xff0c;常常辅助我们开发人员快速查看服务运行状态在微服务架构中&#xff0c;Spring Boot Admin通…

微信小程序:6.事件

什么事事件 事件就是渲染层到逻辑层的通讯方式&#xff0c;比如提交表单&#xff0c;按钮点击都可以看作一个事件。 小程序中常用的事件 事件对象属性列表 当事件回调时&#xff0c;会收到一个事件对象event&#xff0c;他详细属性如夏表所示&#xff1a; target和curren…

微信小程序关于主包大小不能超过1.5MB的问题

常规的解决办法有以下几种 1、把资源文件改成远程服务器的&#xff0c;比如png这些 2、进入如图的分析页面&#xff0c;能明确知道你哪个插件包太大&#xff0c;我这里之前echart的包就1mb&#xff0c;现在给他缩减到了500kb的样子 3、解决vant等npm包太大的问题&#xff0c…

SpringSecurity + Oauth2 + jwt实现单点登录

文章目录 前言一、springsecurity oauth2 redis方式的缺点二、oauth2认证的4种模式的选择三、认证服务器的编写 第一步、创建WebSecurity配置类第二步、创建jwt仓库配置类第三步、创建UserDetailsService类第四步、创建认证服务器配置类 四、测试认证服务器的功能 1.创建Login…

vivado 使用“链路 (Links)”窗口查看和更改链路设置

使用“链路 (Links) ”窗口查看和更改链路设置 创建链路后 &#xff0c; 就会将其添加到“ Links ”视图 &#xff08; 请参阅下图 &#xff09; 中 &#xff0c; 该视图是更改链路设置和查看状态的主要方法 &#xff0c; 也是最佳方法。 “ Links ”窗口中的每一行都对应 1 …

5、Flink事件时间之Watermark详解

1&#xff09;生成 Watermark 1.Watermark 策略简介 为了使用事件时间语义&#xff0c;Flink 应用程序需要知道事件时间戳对应的字段&#xff0c;即数据流中的每个元素都需要拥有可分配的事件时间戳。 通过使用 TimestampAssigner API 从元素中的某个字段去访问/提取时间戳。…

新媒体运营-----短视频运营-----PR视频剪辑----抠像及美颜磨皮

新媒体运营-----短视频运营-----PR视频剪辑-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/138079659 文章目录 1. 超级键抠像绿(蓝)幕背景2. 常规视频抠像3. 美颜磨皮 1. 超级键抠像绿(蓝)幕背景 如果我们的素材是在摄影棚进行…

积极应对半导体测试挑战 加速科技助力行业“芯”升级

在全球半导体产业高速发展的今天&#xff0c;中国“芯”正迎来前所未有的发展机遇。AI、5G、物联网、自动驾驶、元宇宙、智慧城市等终端应用方兴未艾&#xff0c;为测试行业带来新的市场规模突破点&#xff0c;成为测试设备未来重要的增量市场。新兴领域芯片产品性能不断提升、…

Java8 Stream常见用法

Stream流的常见用法&#xff1a; 1.利用stream流特性把数组转list集合 //定义一个数组Integer[] array {5,2,1,6,4,3};//通过stream特性把数组转list集合List<Integer> list Arrays.stream(array).collect(Collectors.toList());//打印结果System.out.println(list);…

Kubernetes - CentOS7搭建k8s_v1.18集群高可用(kubeadm/二进制包部署方式)实测配置验证手册

Kubernetes - CentOS7搭建k8s集群高可用&#xff08;kubeadm/二进制包部署方式&#xff09;实测配置验证手册 前言概述&#xff1a; 一、Kubernetes—k8s是什么 Kubernetes 这个名字源于希腊语&#xff0c;意为“舵手“或”飞行员"。 Kubernetes&#xff0c;简称K8s&#…

计算机网络大框架图形

如标题&#xff0c;精心画了一个计算机网络的框架性的图&#xff0c;包含了计算机网络的核心思想&#xff0c;在此分享和备份下。各层具体协议参考TCP/IP常用协议栈图解-CSDN博客

[论文阅读] 3D感知相关论文简单摘要

Adaptive Fusion of Single-View and Multi-View Depth for Autonomous Driving 提出了一个单、多视图融合深度估计系统&#xff0c;它自适应地集成了高置信度的单视图和多视图结果 动态选择两个分支之间的高置信度区域执行融合 提出了一个双分支网络&#xff0c;即一个以单…

uniapp 微信小程序 获取openid,手机号进行登录,配合后端

流程&#xff1a;登录注册功能,通过uni.getUserProfile获取wxcode,通过wxcode传给后端获取openid,sessionkey,unionid。 通过<u-button type"success" open-type"getPhoneNumber" getphonenumber"decryptPhoneNumber">一键登录</u-butt…

HTML批量文件上传方案——图像预览方式

作者:私语茶馆 1.HTML多文件上传的关键方案 多文件上传包括:文件有效性校验,文件预览、存储和进度展示多个方面,本章节介绍的是文件预览的实现方案。 2.文件上传前预览 2.1.效果 选择文件前: 选择文件后: 2.2.CSS文件代码 StorageCenter.css代码 html {font-family:…