SystemUI StatusBar流程梳理

SystemUI之StatusBar状态栏

  • 布局结构
  • SystemUI StatusBar流程梳理_第1张图片

 

 

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

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

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

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

二、代码控制流程

2.1StatusBar创建准备工作

2.1.1StatusBar :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.1StatusBar :createAndAddWindows()

createAndAddWindows() à makeStatusBarView(result)

makeStatusBarView负责状态栏具体创建

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

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.   
  27.     mHeadsUpManager.setup(mVisualStabilityManager);  
  28.     ……
  29.     createNavigationBar(result);  
  30.     ……
  31.     // 通知背景、Qs背景等
  32.     ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind);  
  33.     ……
  34.     // receive broadcasts  
  35.     registerBroadcastReceiver();  
  36.     ……
  37. }  

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,这个是一个继承FrameLayoutView。所以能比较初步的知道这个子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();  
  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加载过程

SystemUI StatusBar流程梳理_第2张图片

 

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

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) à addNotificationInternalicon首次添加)

aStatusBarNotification 里面的信息转换成NotificationEntry

b、绑定一些监听。

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

2.updateNotification à updateNotificationInternal

View显示有关的内容:

à updateNotifications à mPresenter.updateNotificationViews(reason)

mPresenterStatusBarNotificationPresenter.java的实例

à updateNotificationViews à mNotificationPanel.updateNotificationViews(reason);

mNotificationIconAreaControllerupdateNotificationIcons  à updateStatusBarIcons

à updateIconsForLayout

  1. /** 
  2.  * Updates the notification icons for a host layout. This will ensure that the notification 
  3.  */  
  4. private void updateIconsForLayout(Function function,  
  5.         NotificationIconContainer hostLayout,……) {  
  6.     ArrayList 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.   
  19.     hostLayout.setChangingViewPositions(true);  
  20.     // Re-sort notification icons  
  21.     final int childCount = hostLayout.getChildCount();  
  22.     for (int i = 0; i < childCount; i++) {  
  23.         View actual = hostLayout.getChildAt(i);  
  24.         StatusBarIconView expected = toShow.get(i);  
  25.         if (actual == expected) {  
  26.             continue;  
  27.         }  
  28.         hostLayout.removeView(expected);  
  29.         hostLayout.addView(expected, i);  
  30.     }  
  31.     ……
  32. }  

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

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

aCollapsedStatusBarFragment.onViewCreated

 SystemUI StatusBar流程梳理_第3张图片

 

以上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)

DarkIconManagerStatusBarIconController的一个内部类,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.   
  6.     if (isNew) {  
  7.         addSystemIcon(index, holder);  //新增
  8.     } else {  
  9.         handleSet(index, holder);  //更新
  10.     }  
  11. }  
  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.   
  6.     mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, hidden, holder));  

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.   
  10.         case TYPE_WIFI:  
  11.             return addSignalIcon(index, slot, holder.getWifiState());  
  12.   
  13.         case TYPE_MOBILE:  
  14.             return addMobileIcon(index, slot, holder.getMobileState());  
  15.     }  
  16.     return null;  
  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,android)