SystemUI之StatusBar状态栏

  • 布局结构

下拉菜单、状态栏都是属于statusbar,结构树上也是属于顶层的super_status_bar.xml(StatusBarWindowView)

从上图可以看出顶层树是super_status_bar,之后会走两个分支status_bar_container和status_bar_expanded。

status_bar_expanded下拉菜单,分快捷图标和通知栏。

status_bar_container状态栏,分左边通知栏和右边系统功能的状态图标显示。

二、代码控制流程

2.1、StatusBar创建准备工作

2.1.1、StatusBar :start()

SystemUIService(extends Service) :onCreate()à 
((SystemUIApplication).startServicesIfNeeded() à mServices[i].start()

StatusBar也是SystemUI的一个服务(并非真正的service),所以它的启动入口也是从start()方法开始。主要做了以下几件事:

1.获取各种服务为后续工作做准备。

2.建立farmework的联系,把自己注册到StatusBarService中以供其他app使用--能在APP层来控制导航栏和状态栏可见

mBarService=IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE));

mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders, fullscreenStackBounds, dockedStackBounds);

3. 创建StatusBar.java :createAndAddWindows() ,并且做一些初始化值

  1. public void start() {
  2. ……
  3. mKeyguardIndicationController.init();
  4. ……
  5. mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
  6. ……
  7. mWindowManagerService = WindowManagerGlobal.getWindowManagerService();    ……
  8. mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
  9. mBarService = IStatusBarService.Stub.asInterface(
  10. ServiceManager.getService(Context.STATUS_BAR_SERVICE));
  11. ……
  12. try {
  13. result = mBarService.registerStatusBar(mCommandQueue);
  14. catch (RemoteException ex) {
  15. ex.rethrowFromSystemServer();
  16. }
  17. createAndAddWindows(result);
  18. ……
  19. }
  1. public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
  2. makeStatusBarView(result);
  3. mNotificationShadeWindowController.attach();
  4. //会将statusbarView添加到window上àmWindowManager.addView(mStatusBarView, mLp);
  5. mStatusBarWindowController.attach();
  6. }

2.1.1、StatusBar :createAndAddWindows()

createAndAddWindows() à makeStatusBarView(result)

makeStatusBarView负责状态栏具体创建

1.加载statusbar设备树super_status_bar :inflateStatusBarWindow(context)-->mPhoneStatusBarWindow(mSuperStatusBarViewFactory.getStatusBarWindowView()),这个设备树的根View是StatusBarWindowView

2.CollapsedStatusBarFragment就是作为加载状态栏的Fragment

  1. // Constructing the view
  2. protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
  3. ……
  4. inflateStatusBarWindow();
  5. ……
  6. //主要是有关notification的服务类获取
  7. mStackScrollerController =
  8. mNotificationPanelViewController.getNotificationStackScrollLayoutController();
  9. ……
  10. FragmentHostManager.get(mPhoneStatusBarWindow)
  11. .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
  12. CollapsedStatusBarFragment statusBarFragment =
  13. (CollapsedStatusBarFragment) fragment;
  14. ……
  15. }).getFragmentManager()
  16. .beginTransaction()
  17. .replace(R.id.status_bar_container,
  18. new CollapsedStatusBarFragment(
  19. mOngoingCallController,
  20. ……
  21. this,
  22. mCommandQueue
  23. ),
  24. CollapsedStatusBarFragment.TAG)
  25. .commit();
  26. mHeadsUpManager.setup(mVisualStabilityManager);
  27. ……
  28. createNavigationBar(result);
  29. ……
  30. // 通知背景、Qs背景等
  31. ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind);
  32. ……
  33. // receive broadcasts
  34. registerBroadcastReceiver();
  35. ……
  36. }
public void attach() {mLp = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,mBarHeight,WindowManager.LayoutParams.TYPE_STATUS_BAR,……
mLp.gravity = Gravity.TOP;……
mWindowManager.addView(mStatusBarView, mLp);……

}

扩展:StatusBar在窗口的位置如何确定 ???

DisplayPolicy.java à layoutStatusBar

2.2、状态栏图标加载及数据初始化(CollapsedStatusBarFragment)

2.2.1、布局加载

  1. @Override
  2. public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
  3. Bundle savedInstanceState) {
  4. return inflater.inflate(R.layout.status_bar, container, false);
  5. }

status_bar.xml的文件:

1.根View :StatusBarWindowView,这个是一个继承FrameLayout的View。所以能比较初步的知道这个子View的界面的加载流程

2.@+id/status_bar_contents 这个LinearLayout,里面包含了@+id/status_bar_left_side  ,状态栏左边部分。这个状态栏左边部分包含了时钟@+id/clock和通知@+id/notification_icon_area

3.@+id/system_icon_area这个也是一个LinearLayout包含了@layout/system_icons,状态栏右边部分,里面包含了电池图标和系统状态图标

系统状态图标还是通知图标都是动态加载

2.2.2、数据加载

1、左边通知图标的添加流程(@+id/notification_icon_area)

a、左边通知view加载过程

  1. @Override
  2. public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
  3. ……
  4. View contents = mStatusBar.findViewById(R.id.status_bar_contents);
  5. ……
  6. mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
  7. mClockView = mStatusBar.findViewById(R.id.clock);
  8. ……
  9. initOperatorName();
  10. initNotificationIconArea();
  11. }
  1. /** Initializes views related to the notification icon area. */
  2. public void initNotificationIconArea() {
  3. ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
  4. mNotificationIconAreaInner =
  5. mNotificationIconAreaController.getNotificationInnerAreaView();
  6. if (mNotificationIconAreaInner.getParent() != null) {
  7. ((ViewGroup) mNotificationIconAreaInner.getParent())
  8. .removeView(mNotificationIconAreaInner);
  9. }
  10. notificationIconArea.addView(mNotificationIconAreaInner);
  11. ……
  12. statusBarCenteredIconArea.addView(mCenteredIconArea);
  13. }

NotificationIconAreaController:这个类主要是用于通知icon的控制类。

mNotificationIconAreaInner是通过加载notification_icon_area而生成的view;

b、左边通知data加载过程

每次系统通知变化的会回调NotificationListenerService的onNotificationPosted

NotificationListener.onNotificationPosted à handler.onNotificationPosted(sbn, rankingMap) à NotificationEntryManager.onNotificationPosted(sbn, rankingMap)

  1. private final NotificationHandler mNotifListener = new NotificationHandler() {
  2. @Override
  3. public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
  4. final boolean isUpdateToInflatedNotif = ……
  5. if (isUpdateToInflatedNotif) {
  6. updateNotification(sbn, rankingMap);
  7. else {
  8. addNotification(sbn, rankingMap);
  9. }
  10. }

1.addNotification(sbn, rankingMap) à addNotificationInternal(icon首次添加)

a、StatusBarNotification 里面的信息转换成NotificationEntry。

b、绑定一些监听。

c、把新添加的信息保持在mPendingNotifications,这个集合保持了所有显示的通知

2.updateNotification à updateNotificationInternal

View显示有关的内容:

à updateNotifications à mPresenter.updateNotificationViews(reason)

mPresenter是StatusBarNotificationPresenter.java的实例

à updateNotificationViews à mNotificationPanel.updateNotificationViews(reason);

mNotificationIconAreaController:updateNotificationIcons  à updateStatusBarIcons

à updateIconsForLayout

  1. /**
  2. * Updates the notification icons for a host layout. This will ensure that the notification
  3. */
  4. private void updateIconsForLayout(Function<NotificationEntry, StatusBarIconView> function,
  5. NotificationIconContainer hostLayout,……) {
  6. ArrayList<StatusBarIconView> toShow = new ArrayList<>(mNotificationEntries.size());
  7. ……
  8. for (int i = 0; i < toShow.size(); i++) {
  9. StatusBarIconView v = toShow.get(i);
  10. hostLayout.removeTransientView(v);
  11. if (v.getParent() == null) {
  12. if (hideDismissed) {
  13. v.setOnDismissListener(mUpdateStatusBarIcons);
  14. }
  15. hostLayout.addView(v, i, params);
  16. }
  17. }
  18. hostLayout.setChangingViewPositions(true);
  19. // Re-sort notification icons
  20. final int childCount = hostLayout.getChildCount();
  21. for (int i = 0; i < childCount; i++) {
  22. View actual = hostLayout.getChildAt(i);
  23. StatusBarIconView expected = toShow.get(i);
  24. if (actual == expected) {
  25. continue;
  26. }
  27. hostLayout.removeView(expected);
  28. hostLayout.addView(expected, i);
  29. }
  30. ……
  31. }

从上面的代码看出updateIconsForLayout含税会把StatusBarIconView添加到NotificationIconContainer这个ViewGroup中,而NotificationIconContainer依据前面的分析是挂载在左边通知区域。到现在整个的通知信息加载流程梳理完成。

2、系统icon的加载 @+id/system_icon_area

aCollapsedStatusBarFragment.onViewCreated

以上把StatusIconContainer保存到IconManager里面:

mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons))

Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);

R.id.statusIcons这个其实是在system_icons.xml里面的StatusIconContainer,这个View是一个LinearLayout(另外一个是BatteryMeterView)。

DarkIconManager是StatusBarIconController的一个内部类,DarkIconManager extends IconManager,IconManager个类里面做的事情是创建StatusBarIconView,部分代码:

bview添加到StatusIconContainer流程

StatusBar.java.start()-->(PhoneStatusBarPolicy)mIconPolicy.init()

PhoneStatusBarPolicy是除了信号的状态Icon的所有系统Icon。而信号的icon就由StatusBarSignalPolicy来做初始化;

PhoneStatusBarPolicy.java

  1. /** Initialize the object after construction. */
  2. public void init() {
  3. ……
  4. // TTY status
  5. updateTTY();
  6. // bluetooth status
  7. updateBluetooth();
  8. // Alarm clock
  9. mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
  10. mIconController.setIconVisibility(mSlotAlarmClock, false);
  11. ……
  12. }

StatusBarIconControllerImpl

setIcon() à addSystemIcon(index, holder) à onIconAdded

  1. @Override
  2. public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
  3. boolean isNew = getIcon(index, holder.getTag()) == null;
  4. super.setIcon(index, holder);
  5. if (isNew) {
  6. addSystemIcon(index, holder);  //新增
  7. else {
  8. handleSet(index, holder);  //更新
  9. }
  10. }
  1. private void addSystemIcon(int index, StatusBarIconHolder holder) {
  2. String slot = getSlotName(index);
  3. int viewIndex = getViewIndex(index, holder.getTag());
  4. boolean hidden = mIconHideList.contains(slot);
  5. mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, hidden, holder));
  6. }

StatusBarIconController.IconManager.onIconAdded--> addHolder

  1. protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked,
  2. StatusBarIconHolder holder) {
  3. if (mBlockList.contains(slot)) {
  4. blocked = true;
  5. }
  6. switch (holder.getType()) {
  7. case TYPE_ICON:
  8. return addIcon(index, slot, blocked, holder.getIcon());
  9. case TYPE_WIFI:
  10. return addSignalIcon(index, slot, holder.getWifiState());
  11. case TYPE_MOBILE:
  12. return addMobileIcon(index, slot, holder.getMobileState());
  13. }
  14. return null;
  15. }
  1. protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
  2. StatusBarIcon icon) {
  3. StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
  4. view.set(icon);
  5. mGroup.addView(view, index, onCreateLayoutParams());
  6. return view;
  7. }

最后会调用addIcon,创建一个StatusBarIconView 添加到mGroup,而mGroup就是我们在所提到的R.id.statusIcons,也就是StatusIconContainer。到现在系统icon就添加到状态栏右边了。

SystemUI StatusBar流程梳理相关推荐

  1. SystemUI QuickSettings流程梳理

    SystemUI之快捷设置Qs加载过程分析 一.布局构成 详细说明: src\com\android\systemui\statusbar\phone\StatusBar.java 快捷设置区域的布局 ...

  2. Android 8.0系统学习(19)--- SystemUI启动流程

    Android 8.0系统学习(19)--- SystemUI启动流程 systemui属于系统级应用,在开机过程中就会启动.具体来讲是在SystemServer进程中startOtherServic ...

  3. Android 4.0 ICS SystemUI浅析——SystemUI启动流程

    阅读Android 4.0源码也有一段时间了,这次是针对SystemUI的一个学习过程.本文只是对SystemUI分析的一个开始--启动流程的分析,网上有很多关于2.3的SystemUI的分析,可4. ...

  4. (四十四)Android O WiFi启动流程梳理

    前言:最近又重新拿起来WiFi模块,从WiFi 各个流程梳理开始复习一下. 参考博客:https://blog.csdn.net/csdn_of_coder/article/details/51541 ...

  5. .16-浅析webpack源码之编译后流程梳理

    这节把编译打包后的流程梳理一下,然后集中处理compile. 之前忽略了一个点,如下: new NodeEnvironmentPlugin().apply(compiler); // 引入插件加载 i ...

  6. 【EventBus】EventBus 源码解析 ( 注册订阅者总结 | EventBus 注册订阅者流程梳理 )

    文章目录 EventBus 注册订阅者流程梳理 EventBus 注册订阅者流程梳理 EventBus 注册订阅者流程梳理 : ① 在 客户端 调用 EventBus.getDefault().reg ...

  7. 【Binder 机制】AIDL 分析 ( AIDL 通信完整流程梳理 )

    文章目录 AIDL 跨进程通信完整流程梳理 1.AIDL 文件编译 2.注册服务 3.IMyAidlInterface.Stub.asInterface 方法获取远程服务 4.IMyAidlInter ...

  8. 在流程梳理的过程中,OA工作组应采用国际先进方法

    进行OA服务建模 服务建模是通过对全部业务流程的全面分析,初步确定业务服务和应用服务,包括服务封装的业务/应用逻辑和对外提供的操作候选. 服务建模的前提是需对业务流程和系统功能非常了解.服务建模的工作 ...

  9. android p wifi一直在扫描_(一百六十八)Android P wifi 扫描失败结果上报流程梳理-扫描上报梳理②...

    接(一百五十五)Android P wifi 扫描失败结果上报流程梳理-扫描上报梳理 扫描失败上报梳理发现梳理的差了很多,特补充 1.WificondScannerImpl @Override pub ...

最新文章

  1. LeetCode: 929. Unique Email Addresses
  2. etymon word write alb pain high alt increase large agency ag lose weight fat assist out~3
  3. 12.2 全局CSS样式
  4. how to resolve error message java.lang.ClassNotFoundException: org.springframework
  5. 幅度和幅值有区别吗_克拉克 (Clark) 变换中等幅值 (2/3) 和等功率 (sqrt(2/3)) 变换的公式推导...
  6. Zookeeper和分布式环境中的假死脑裂问题(转)
  7. WebService的基本概念:java webservice,什么是webservice
  8. 【JEECG技术文档】表单配置-树形表单
  9. 网赚新手必读:Google Adsense五条法则
  10. 101107 ~101113
  11. SQL语句中查找字符的位置
  12. 鸿蒙事业单位专业技术,事业单位专业技术岗考什么?
  13. Android国际化,简体和繁体切换
  14. 如何制作手机海报?手把手教你在线自制手机海报
  15. 2022还不知道登陆邮箱账号怎么填写?个人邮箱登录注册流程看详解
  16. 管理学十大经典图书推荐
  17. macbook air扩展显示器全屏滑动怎样不一起滑动?
  18. InDesign Quick Start InDesign快速入门 Lynda课程中文字幕
  19. 工程测量:坐标正反算公式
  20. H5canvas(绘制矩形,绘制圆形,绘制线段,绘制文字,绘制曲线)

热门文章

  1. 视频教程-全行业IT售前入门课程-其他
  2. C++ char 转 int
  3. 数据结构fractions
  4. AWS(Amazon Web Services, 亚马逊网络服务系统)简介
  5. 【特征工程】 离散型变量 映射成 数字
  6. SC9832 Android7.0 基准仓库建立
  7. 基于钣金工艺优化的钣金件结构设计
  8. 人工智能-机器学习-深度学习-电子书大全
  9. 采购订单打印并预览PDF
  10. 2021-06-23(2)