前言

上一篇我们具体分析了SystemUI的启动流程,在SystemServer的startOtherServices方法中,会启动SystemUIService服务,SystemUIService服务的onCreate方法会继续调用SystemUIApplication的startServicesIfNeeded方法,在该方法中会获取SystemUI组件各个类的具体路径,并通过反射创建对应的实例对象,然后依次调用每个组件的start() 方法启动相关类的服务,启动完成后,又会再次调用该组件的onBootCompleted( ) 方法。

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

    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];//具体系统控件类的完整路径...Class cls = Class.forName(clsName);mServices[i] = (SystemUI) cls.newInstance();//通过反射创建实例对象...mServices[i].mContext = this;mServices[i].mComponents = mComponents;mServices[i].start(); //调用start()启动...if (mBootCompleted) {mServices[i].onBootCompleted(); //启动完毕,调用对应的onBootCompleted()方法}}...mServicesStarted = true;}

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

    <string-array name="config_systemUIServiceComponents" translatable="false"><item>com.android.systemui.Dependency</item><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><item>com.android.systemui.SystemBars</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.fingerprint.FingerprintDialogImpl</item><item>com.android.systemui.SliceBroadcastRelayHandler</item></string-array>

对这些 SystemUI服务 做一点介绍:

  • com.android.systemui.Dependency 是为了创建全局可用的依赖关系。
  • com.android.systemui.SystemBars创建整个SystemUI视图的入口类。
  • com.android.systemui.recents.Recents 最近任务
  • com.android.systemui.volume.VolumeUI 音量控制
  • com.android.systemui.pip.PipUI 画中画
  • com.android.systemui.statusbar.CommandQueue 是一个 Binder 类,它会被StatusBar注册到 StatusBarManagerService 中,用于接收StatusBarManagerService服务端的消息。

一、创建StatusBar

1、上面说过,SystemBars这个组件是整个SystemUI视图创建的入口类,它被启动时会调用 start() 方法,先看下该类的 start() 方法:

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

public class SystemBars extends SystemUI {...@Overridepublic void start() {createStatusBarFromConfig();//通过配置创建系统状态栏}...private void createStatusBarFromConfig() {final String clsName = mContext.getString(R.string.config_statusBarComponent);//获取系统状态栏对应类的全路径if (clsName == null || clsName.length() == 0) {throw andLog("No status bar component configured", null);}Class<?> cls = null;try {cls = mContext.getClassLoader().loadClass(clsName);//加载对应的类对象} catch (Throwable t) {throw andLog("Error loading status bar component: " + clsName, t);}try {mStatusBar = (SystemUI) cls.newInstance();//通过反射创建实例对象} catch (Throwable t) {throw andLog("Error creating status bar component: " + clsName, t);}mStatusBar.mContext = mContext;mStatusBar.mComponents = mComponents;mStatusBar.start();//调用系统状态栏的start方法}

从中可以知道,该方法中先读取 value/config.xml文件中config_statusBarComponent的值

<string name="config_statusBarComponent">com.android.systemui.statusbar.phone.StatusBar</string>

该数值其实就是状态栏所对应类的完整路径,然后再通过反射创建出具体的StatusBar对象实例,最后调用StatusBar的start()方法。

2、StatusBar的start方法如下所示,该类的start()方法代码较多,这里我们只看重点,在该方法里面有调用createAndAddWindows()方法,然后再调用addStatusBarWindow()方法,该方法又会继续调用makeStatusBarView方法,makeStatusBarView方法具体来构建系统状态栏视图。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

public class StatusBar extends SystemUI implements DemoMode,DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {...@Overridepublic void start() {...createAndAddWindows(); //创建整个SystemUI视图并添加到WindowManager中...}...public void createAndAddWindows() {addStatusBarWindow();}private void addStatusBarWindow() {makeStatusBarView(); //创建整个SystemUI视图...}...
}

二、通过布局文件构建StatusBar所对应的视图

1、StatusBar的makeStatusBarView方法如下,该方法会继续调用inflateStatusBarWindow方法,将R.layout.super_status_bar布局文件构建成对应的视图。

    protected void makeStatusBarView() {final Context context = mContext;updateDisplaySize(); // populates mDisplayMetricsupdateResources();updateTheme();//实例化整个SystemUI视图,包括状态栏,通知面版,锁屏inflateStatusBarWindow(context);...}protected void inflateStatusBarWindow(Context context) {//实例化整个SystemUI视图,包括状态栏,通知面版,锁屏mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null);}

2、布局super_status_bar.xmlz其实就是整个SystemUI视图,它的的具体内容如下所示:

frameworks/base/packages/SystemUI/res/layout/super_status_bar.xml

<com.android.systemui.statusbar.phone.StatusBarWindowViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:sysui="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"><com.android.systemui.statusbar.BackDropViewandroid:id="@+id/backdrop"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="gone"sysui:ignoreRightInset="true"><ImageView android:id="@+id/backdrop_back"android:layout_width="match_parent"android:scaleType="centerCrop"android:layout_height="match_parent" /><ImageView android:id="@+id/backdrop_front"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"android:visibility="invisible" /></com.android.systemui.statusbar.BackDropView><com.android.systemui.statusbar.ScrimViewandroid:id="@+id/scrim_behind"android:layout_width="match_parent"android:layout_height="match_parent"android:importantForAccessibility="no"sysui:ignoreRightInset="true"/><!--系统状态栏容器--><FrameLayoutandroid:id="@+id/status_bar_container"android:layout_width="match_parent"android:layout_height="wrap_content" /><!--车载模式的布局  --><ViewStub android:id="@+id/fullscreen_user_switcher_stub"android:layout="@layout/car_fullscreen_user_switcher"android:layout_width="match_parent"android:layout_height="match_parent"/><!--整个下拉通知面版,包括锁屏界面--><include layout="@layout/status_bar_expanded"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="invisible" /><!--状态栏图标下的SeekBar布局 --><include layout="@layout/brightness_mirror" /><com.android.systemui.statusbar.ScrimViewandroid:id="@+id/scrim_in_front"android:layout_width="match_parent"android:layout_height="match_parent"android:importantForAccessibility="no"sysui:ignoreRightInset="true"/></com.android.systemui.statusbar.phone.StatusBarWindowView>

根视图StatusBarWindowView是一个FrameLayout,状态栏显示在最下面,然后通知面版会覆盖状态栏,最后还有一个底部视图在最上面。另外值得注意的一点就是id为status_bar_container的组件就是系统状态栏,接下来会向这个容器中添加状态栏视图。

三、系统状态栏所对应的布局文件

1、继续看StatusBar的makeStatusBarView方法,我们就会发现,id为status_bar_container所对应的Fragment其实就是状态栏,而它所对应的具体实现类就是CollapsedStatusBarFragment。

    protected void makeStatusBarView() {final Context context = mContext;updateDisplaySize();updateResources();updateTheme();//实例化整个SystemUI视图,包括状态栏,通知面版,锁屏inflateStatusBarWindow(context);...// 创建状态栏视图FragmentHostManager.get(mStatusBarWindow).addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {CollapsedStatusBarFragment statusBarFragment =(CollapsedStatusBarFragment) fragment;// 用通知图标控制器,初始化了通知图标区域和中心图标区域,并且显示出来statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);mStatusBarView = (PhoneStatusBarView) fragment.getView();mStatusBarView.setBar(this);mStatusBarView.setPanel(mNotificationPanel);mStatusBarView.setScrimController(mScrimController);mStatusBarView.setBouncerShowing(mBouncerShowing);if (mHeadsUpAppearanceController != null) {// This view is being recreated, let's destroy the old onemHeadsUpAppearanceController.destroy();}mHeadsUpAppearanceController = new HeadsUpAppearanceController(mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow);setAreThereNotifications();checkBarModes();}).getFragmentManager().beginTransaction()// CollapsedStatusBarFragment实现了状态栏的添加.replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),CollapsedStatusBarFragment.TAG).commit();...}

可以看到CollapsedStatusBarFragment代表的就是状态栏视图,这个视图被添加到ID为status_bar_container的容器中。

2、接下来继续分析CollapsedStatusBarFragment的生命周期,即可知道状态栏的创建过程。这里创建视图的地方就在CollapsedStatusBarFragment的onCreateView方法中,该方法会将status_bar.xml布局文件转化为对应的视图。

public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {...@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,Bundle savedInstanceState) {//系统状态栏所对应的布局文件return inflater.inflate(R.layout.status_bar, container, false);}...
}

3、status_bar.xml 就是状态栏视图布局,该布局文件的具体内容如下所示:

<com.android.systemui.statusbar.phone.PhoneStatusBarViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"android:layout_width="match_parent"android:layout_height="@dimen/status_bar_height"android:id="@+id/status_bar"android:background="@drawable/system_bar_background"android:orientation="vertical"android:focusable="false"android:descendantFocusability="afterDescendants"android:accessibilityPaneTitle="@string/status_bar"><ImageViewandroid:id="@+id/notification_lights_out"android:layout_width="@dimen/status_bar_icon_size"android:layout_height="match_parent"android:paddingStart="@dimen/status_bar_padding_start"android:paddingBottom="2dip"android:src="@drawable/ic_sysbar_lights_out_dot_small"android:scaleType="center"android:visibility="gone"/><!--状态栏  --><LinearLayout android:id="@+id/status_bar_contents"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingStart="@dimen/status_bar_padding_start"android:paddingEnd="@dimen/status_bar_padding_end"android:orientation="horizontal"><ViewStubandroid:id="@+id/operator_name"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout="@layout/operator_name" /><FrameLayoutandroid:layout_height="match_parent"android:layout_width="0dp"android:layout_weight="1"><include layout="@layout/heads_up_status_bar_layout" /><!--状态栏左边视图,依次显示运营商名字,时间,通知图标--><LinearLayoutandroid:id="@+id/status_bar_left_side"android:layout_height="match_parent"android:layout_width="match_parent"android:clipChildren="false"><!-- 时钟信息 --><com.android.systemui.statusbar.policy.Clockandroid:id="@+id/clock"android:layout_width="wrap_content"android:layout_height="match_parent"android:textAppearance="@style/TextAppearance.StatusBar.Clock"android:singleLine="true"android:paddingStart="@dimen/status_bar_left_clock_starting_padding"android:paddingEnd="@dimen/status_bar_left_clock_end_padding"android:gravity="center_vertical|start"/><!--通知图标区域--><com.android.systemui.statusbar.AlphaOptimizedFrameLayoutandroid:id="@+id/notification_icon_area"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="horizontal"android:clipChildren="false"/></LinearLayout></FrameLayout><android.widget.Spaceandroid:id="@+id/cutout_space_view"android:layout_width="0dp"android:layout_height="match_parent"android:gravity="center_horizontal|center_vertical"/><!--系统图标区,由状态图标集和电池图标组成,状态图标集由wifi,bt等等组成--><com.android.keyguard.AlphaOptimizedLinearLayoutandroid:id="@+id/system_icon_area"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="horizontal"android:gravity="center_vertical|end"><include layout="@layout/system_icons" /></com.android.keyguard.AlphaOptimizedLinearLayout></LinearLayout><ViewStubandroid:id="@+id/emergency_cryptkeeper_text"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout="@layout/emergency_cryptkeeper_text"/></com.android.systemui.statusbar.phone.PhoneStatusBarView>

从这个布局可以分析出状态栏从左到右到底显示了什么。

  • 最左边的一块区域,依次显示运营商名字,时间,通知图标。
  • 中间一块区域。
  • 然后是最右边一块区域,显示的是状态图标(例如bt, wifi),以及电池图标。

这样一来,我们就对整个状态栏上的布局有个了解,后续的篇章我们将会继续分析下状态上的状态图标(例如bt, wifi)是如何显示上去的。

四、系统下拉通知窗口的布局文件

1、重新回到第二步,继续看StatusBar所对应的super_status_bar.xml,该布局文件中
include所包含的status_bar_expanded就是系统下拉的通知窗口的布局文件。

<com.android.systemui.statusbar.phone.NotificationPanelViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:systemui="http://schemas.android.com/apk/res-auto"android:id="@+id/notification_panel"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/transparent" ><!--锁屏时的时钟布局  --><includelayout="@layout/keyguard_status_view"android:visibility="gone" /><com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainerandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="@integer/notification_panel_layout_gravity"android:id="@+id/notification_container_parent"android:clipToPadding="false"android:clipChildren="false"><FrameLayoutandroid:id="@+id/qs_frame"android:layout="@layout/qs_panel"android:layout_width="@dimen/qs_panel_width"android:layout_height="match_parent"android:layout_gravity="@integer/notification_panel_layout_gravity"android:clipToPadding="false"android:clipChildren="false"systemui:viewType="com.android.systemui.plugins.qs.QS" /><!-- 通知栏区域 --><com.android.systemui.statusbar.stack.NotificationStackScrollLayoutandroid:id="@+id/notification_stack_scroller"android:layout_marginTop="@dimen/notification_panel_margin_top"android:layout_width="@dimen/notification_panel_width"android:layout_height="match_parent"android:layout_gravity="@integer/notification_panel_layout_gravity"android:layout_marginBottom="@dimen/close_handle_underlap" /><include layout="@layout/ambient_indication"android:id="@+id/ambient_indication_container" /><!--锁屏切换 --><ViewStubandroid:id="@+id/keyguard_user_switcher"android:layout="@layout/keyguard_user_switcher"android:layout_height="match_parent"android:layout_width="match_parent" /><!--锁屏下的状态栏 --><includelayout="@layout/keyguard_status_bar"android:visibility="invisible" /><Buttonandroid:id="@+id/report_rejected_touch"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="@dimen/status_bar_header_height_keyguard"android:text="@string/report_rejected_touch"android:visibility="gone" /></com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer><!--锁屏界面底部的图标 --><includelayout="@layout/keyguard_bottom_area"android:visibility="gone" /><com.android.systemui.statusbar.AlphaOptimizedViewandroid:id="@+id/qs_navbar_scrim"android:layout_height="96dp"android:layout_width="match_parent"android:layout_gravity="bottom"android:visibility="invisible"android:background="@drawable/qs_navbar_scrim" /></com.android.systemui.statusbar.phone.NotificationPanelView>

Android 9.0系统源码_SystemUI(二)StatusBar系统状态栏的创建流程相关推荐

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

    一.SystemUI 介绍 1.初步认识SystemUI Android 的 SystemUI 其实就是 Android 的系统界面,它包括了界面上方的状态栏 status bar,下方的导航栏Nav ...

  2. Android 12系统源码_SystemUI(一)SystemUI的启动流程

    前言 Android 的 SystemUI 其实就是 Android 的系统界面,它包括了界面上方的状态栏 status bar,下方的导航栏Navigation Bar,锁屏界面 Keyguard ...

  3. 【转】Ubuntu 14.04.3上配置并成功编译Android 6.0 r1源码

    http://www.linuxidc.com/Linux/2016-01/127292.htm 终于成功把Android 6.0 r1源码的源码编译.先上图,这是在Ubuntu中运行的Android ...

  4. 仿阿姨帮|58到家上门O2O系统源码( BAOCMS二次开发 )

    [实例简介] 仿阿姨帮|58到家上门O2O系统源码(BAOCMS二次开发 七牛云)是一款PHP MYSQL开发制作的在线上门O2O系统,,PC WAP 微信端等功能,在BAOCMS基础上二次开发的东西 ...

  5. Android 11.0 Settings源码分析 - 主界面加载

    Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...

  6. Android 4.0.1 源码下载,编译和运行

    [牛人分享]Android 4.0.1 源码下载,编译和运行 转自 http://blog.csdn.net/rambo2188/article/details/6943382 ----------- ...

  7. android 4.0模拟器启动不了,Android 4.0 framework源码修改编译,模拟器运行不起来,求助...

    当前位置:编程学习 > wap >> Android 4.0 framework源码修改编译,模拟器运行不起来,求助 我下载编译了android 4.0 ICS的源码,然后能利用编译 ...

  8. java计算机毕业设计物流站环境监测系统源码+lw文档+系统+数据库

    java计算机毕业设计物流站环境监测系统源码+lw文档+系统+数据库 java计算机毕业设计物流站环境监测系统源码+lw文档+系统+数据库 本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 ...

  9. javaweb JAVA JSP手机销售系统购物系统jsp购物系统购物商城系统源码(jsp电子商务系统)网上手机店在线销售

    JSP手机销售系统购物系统jsp购物系统购物商城系统源码(jsp电子商务系统)网上手机店在线销售 常见的Javaweb题材有 理财系统,就业管理系统,汽车租赁,简易网盘,疫情数据查看,在线招标房,屋租 ...

  10. javaweb JAVA JSP水果销售系统购物系统jsp购物系统购物商城系统源码(jsp电子商务系统)网上水果店在线销售

    javaweb JAVA JSP水果销售系统购物系统jsp购物系统购物商城系统源码(jsp电子商务系统)网上水果店在线销售 常见的Javaweb题材有 理财系统,就业管理系统,汽车租赁,简易网盘,疫情 ...

最新文章

  1. 横河川仪压力变送器调零_YOKOGAWA/横河EJX110A差压变送器的性能误差和精度介绍!...
  2. 智能合约重构社会契约 (3)智能合约的自动触发
  3. java的spinner_java中的spinner | 学步园
  4. mysql驱动rpm和jar_mysql5.7.11对应的JDBC驱动是哪个版本
  5. Nodejs获取MySQL数据_nodejs同步调用获取mysql数据时遇到的大坑
  6. (二十六)深度学习目标检测:Fast-RCNN
  7. 个人网页制作 大学生个人网页设计 个人网站模板 简单静态HTML个人网页作品
  8. 基于hilbert变换的数字信号_hilbert变换
  9. C#中splitContainer用法
  10. Statement和PreparedStatement的区别
  11. 马斯克血洗推特!传机器学习裁员90%,团队直接解散
  12. ps批量修改图片尺寸
  13. 微信小程序-005-投票功能-设置投票
  14. 新建word 无法切换输入法_为什么word文件中无法切换输入法?
  15. 位运算bitwise_and和bitwise_not函数
  16. 乐鑫Esp32学习之旅11 入门 乐鑫esp-adf 音频框架开发,造一个蓝牙耳机,实现切换歌曲,获取歌曲信息等功能。(附带Demo)
  17. 游戏帧同步和状态同步
  18. html文档以标签开始,HTML从零开始——文本标签
  19. html5 meter样式,css – Chrome中的HTML5 Meter样式
  20. 数据结构-线性表的顺序、链式存储结构

热门文章

  1. Origin画图笔记
  2. Firefox OS简单介绍
  3. ffmpeg学习日记701-报错-co located POCs unavailable
  4. Angularjs之模块(angular.module('myApp', [])参数)
  5. 旅行青蛙南の旅旅行券_旅行时查找WiFi
  6. ‘git clone‘ failed with status 128
  7. Python 批量获取今日头条街拍美图
  8. CS1703 C# Multiple assemblies with equivalent xxx... and. Remove one of the duplicate references.
  9. 国科大学习资料--人工智能原理与算法-第四次作业解析(学长整理)
  10. 加油站-问题详解(暴力-整体-贪心)