android12 SystemUI之StatusBar启动

160 阅读15分钟

StatusBar继承SystemUI,在开机启动的时候,被SystemUIService调用StatusBar.start()执行初始化

//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@Override
public void onCreate() {
    super.onCreate();
    // Start all of SystemUI
    ((SystemUIApplication) getApplication()).startServicesIfNeeded();
    ...
    
}

//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java)
public void startServicesIfNeeded() {
          String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
          startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
      }

//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java)
public String[] getSystemUIServiceComponents(Resources resources) {
          return resources.getStringArray(R.array.config_systemUIServiceComponents);
      }
  
//frameworks/base/packages/SystemUI/res/values/config.xml)
<string-array name="config_systemUIServiceComponents" translatable="false">
315         <item>com.android.systemui.util.NotificationChannels</item>
316         <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
317         <item>com.android.systemui.recents.Recents</item>
318         <item>com.android.systemui.volume.VolumeUI</item>
319         <item>com.android.systemui.statusbar.phone.StatusBar</item>
320         <item>com.android.systemui.usb.StorageNotification</item>
321         <item>com.android.systemui.power.PowerUI</item>
322         <item>com.android.systemui.media.RingtonePlayer</item>
323         <item>com.android.systemui.keyboard.KeyboardUI</item>
324         <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
325         <item>@string/config_systemUIVendorServiceComponent</item>
326        <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
327         <item>com.android.systemui.LatencyTester</item>
328    <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
329         <item>com.android.systemui.ScreenDecorations</item>
330         <item>com.android.systemui.biometrics.AuthController</item>
331         <item>com.android.systemui.SliceBroadcastRelayHandler</item>
332<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
333<item>com.android.systemui.theme.ThemeOverlayController</item>
334       <item>com.android.systemui.accessibility.WindowMagnification</item>
335         <item>com.android.systemui.accessibility.SystemActions</item>
336         <item>com.android.systemui.toast.ToastUI</item>
337         <item>com.android.systemui.wmshell.WMShell</item>
338     </string-array>

启动config.xml配置的服务(实际就是启动继承了SystemUI的java类)

 private void startServicesIfNeeded(String metricsPrefix, String[] services) {
          if (mServicesStarted) {
              return;
          }
          mServices = new SystemUI[services.length];
          ...
              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;
              } catch (ClassNotFoundException
                      | NoSuchMethodException
                      | IllegalAccessException
                      | InstantiationException
                      | InvocationTargetException ex) {
                  throw new RuntimeException(ex);
              }
  
             ...
             mServices[i].start();
             ...
  
              }
              if (mBootCompleteCache.isBootComplete()) {
                  mServices[i].onBootCompleted();
              }
  
          mServicesStarted = true;
      }

启动StatusBar(启动状态栏,通知栏,导航栏)

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

 @Override
      public void start() {

          ...
          //获取IStatusBarService实例,
          //IStatusBarService=StatusBarManagerService是系统服务,
          //会保存状态栏的状态信息,运行在SystemServer进程。
          //操作状态栏的请求会通过IStatusBarService发送给SystemUI。
          //对SystemUI而言StatusBarManagerService更像客户端。
          mBarService = IStatusBarService.Stub.asInterface(
                  ServiceManager.getService(Context.STATUS_BAR_SERVICE));
  
          mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
   
           ...  
          // Connect in to the status bar manager service
          mCommandQueue.addCallback(this);
  
  
          RegisterStatusBarResult result = null;
          try {
              //CommandQueue继承IStatusBar.Stub,是IStatusBar的Bn端,
              //通过注册保存到IStatusBarService中。
              result = mBarService.registerStatusBar(mCommandQueue);
          } catch (RemoteException ex) {
              ex.rethrowFromSystemServer();
          }
  
          //创建状态栏,通知栏,导航栏
          createAndAddWindows(result);

          setUpPresenter();
          ...
  

          // Set up the initial icon state
         
          int numIcons = result.mIcons.size();
          for (int i = 0; i < numIcons; i++) {
              mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i));
          }
 
          // Lastly, call to the icon policy to install/update all the icons.
          //PhoneStatusBarPolicy mIconPolicy  初始化状态栏图标
          mIconPolicy.init();
  
          mKeyguardStateController.addCallback(this);
          startKeyguard();
          ...

    }

注册CommandQueue到StatusBarManagerService,同时返回服务端保存的图标列表

//frameworks/base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java)
 public RegisterStatusBarResult registerStatusBar(IStatusBar bar) {
         enforceStatusBarService();
  
         Slog.i(TAG, "registerStatusBar bar=" + bar);
         mBar = bar;
         mDeathRecipient.linkToDeath();
         notifyBarAttachChanged();
         final ArrayMap<String, StatusBarIcon> icons;
         synchronized (mIcons) {
             icons = new ArrayMap<>(mIcons);
         }
         synchronized (mLock) {
             // TODO(b/118592525): Currently, status bar only works on the default display.
             // Make it aware of multi-display if needed.
             final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
             final int[] transientBarTypes = new int[state.mTransientBarTypes.size()];
             for (int i = 0; i < transientBarTypes.length; i++) {
                 transientBarTypes[i] = state.mTransientBarTypes.valueAt(i);
             }
             return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
                      state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis,
                      state.mImeBackDisposition, state.mShowImeSwitcher,
                      gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken,
                      state.mNavbarColorManagedByIme, state.mBehavior, state.mFullscreen,
                      transientBarTypes);
          }
      }

PhoneStatusBarPolicy初始化状态栏图标入口

  • PhoneStatusBarPolicy:决定了哪些图标应在开机时加载到状态栏。它会根据系统状态(如蓝牙是否开启、是否有闹钟等)来显示和隐藏系统图标。
  • StatusBar:SystemUI的主入口,负责初始化整体布局并实例。化 PhoneStatusBarPolicy。
  • StatusBarManagerService:系统服务,负责接收并管理来自各个应用的图标更新请求。
  • IconManager:实际负责将 StatusBarIconView 添加到状态栏布局中。
  • StatusBarIconView:负责单个图标的具体显示和更。
  • StatusBarIconControllerImpl:作为中间层,将 PhoneStatusBarPolicy 的控制指令分发到具体的 IconManager 去执行。
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
    public void init() {
          // listen for broadcasts
          IntentFilter filter = new IntentFilter();
  
          filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
          filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
          filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
          filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
          filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
          filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
          mBroadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter, mHandler);
          Observer<Integer> observer = ringer -> mHandler.post(this::updateVolumeZen);
  
          mRingerModeTracker.getRingerMode().observeForever(observer);
          mRingerModeTracker.getRingerModeInternal().observeForever(observer);
  
          // listen for user / profile change.
          try {
              mIActivityManager.registerUserSwitchObserver(mUserSwitchListener, TAG);
          } catch (RemoteException e) {
              // Ignore
          }
  
          // TTY status
          updateTTY();
  
          // bluetooth status
          updateBluetooth();
  
          // Alarm clock
          //private final StatusBarIconController mIconController;
          //mIconController在构造函数中创建,创建的时候就会去加载配置的系统状态栏图标
          //StatusBarIconController实现类StatusBarIconControllerImpl
          //设置图标
          mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
          mIconController.setIconVisibility(mSlotAlarmClock, false);
  
          // zen
          mIconController.setIcon(mSlotZen, R.drawable.stat_sys_dnd, null);
          mIconController.setIconVisibility(mSlotZen, false);
  
          // vibrate
          mIconController.setIcon(mSlotVibrate, R.drawable.stat_sys_ringer_vibrate,
                  mResources.getString(R.string.accessibility_ringer_vibrate));
          mIconController.setIconVisibility(mSlotVibrate, false);
          // mute
          mIconController.setIcon(mSlotMute, R.drawable.stat_sys_ringer_silent,
                  mResources.getString(R.string.accessibility_ringer_silent));
          mIconController.setIconVisibility(mSlotMute, false);
          updateVolumeZen();
  
          // cast
          mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);
          mIconController.setIconVisibility(mSlotCast, false);
  
          // hotspot
          mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
                  mResources.getString(R.string.accessibility_status_bar_hotspot));
          mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());
  
          // managed profile
          mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
                  mResources.getString(R.string.accessibility_managed_profile));
          mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible);
  
          // data saver
          mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
                  mResources.getString(R.string.accessibility_data_saver_on));
          mIconController.setIconVisibility(mSlotDataSaver, false);
  
  
          // privacy items
          String microphoneString = mResources.getString(PrivacyType.TYPE_MICROPHONE.getNameId());
          String microphoneDesc = mResources.getString(
                  R.string.ongoing_privacy_chip_content_multiple_apps, microphoneString);
          mIconController.setIcon(mSlotMicrophone, PrivacyType.TYPE_MICROPHONE.getIconId(),
                  microphoneDesc);
          mIconController.setIconVisibility(mSlotMicrophone, false);
  
          String cameraString = mResources.getString(PrivacyType.TYPE_CAMERA.getNameId());
          String cameraDesc = mResources.getString(
                  R.string.ongoing_privacy_chip_content_multiple_apps, cameraString);
          mIconController.setIcon(mSlotCamera, PrivacyType.TYPE_CAMERA.getIconId(),
                  cameraDesc);
          mIconController.setIconVisibility(mSlotCamera, false);
  
          mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
                  mResources.getString(R.string.accessibility_location_active));
          mIconController.setIconVisibility(mSlotLocation, false);
  
          // sensors off
          mIconController.setIcon(mSlotSensorsOff, R.drawable.stat_sys_sensors_off,
                  mResources.getString(R.string.accessibility_sensors_off_active));
          mIconController.setIconVisibility(mSlotSensorsOff,
                  mSensorPrivacyController.isSensorPrivacyEnabled());
  
          // screen record
          mIconController.setIcon(mSlotScreenRecord, R.drawable.stat_sys_screen_record, null);
          mIconController.setIconVisibility(mSlotScreenRecord, false);
  
          mRotationLockController.addCallback(this);
          mBluetooth.addCallback(this);
          mProvisionedController.addCallback(this);
          mZenController.addCallback(this);
          mCast.addCallback(mCastCallback);
          mHotspot.addCallback(mHotspotCallback);
          mNextAlarmController.addCallback(mNextAlarmCallback);
          mDataSaver.addCallback(this);
          mKeyguardStateController.addCallback(this);
          mPrivacyItemController.addCallback(this);
          mSensorPrivacyController.addCallback(mSensorPrivacyListener);
          mLocationController.addCallback(this);
          mRecordingController.addCallback(this);
  
          mCommandQueue.addCallback(this);
      }

调用StatusBarIconControllerImpl设置状态栏图标资源,名字

//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java)
public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
          int index = getSlotIndex(slot);
          StatusBarIconHolder holder = getIcon(index, 0);
          if (holder == null) {
              StatusBarIcon icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
                      Icon.createWithResource(
                              mContext, resourceId), 0, 0, contentDescription);
              holder = StatusBarIconHolder.fromIcon(icon);
              setIcon(index, holder);
          } else {
              holder.getIcon().icon = Icon.createWithResource(mContext, resourceId);
              holder.getIcon().contentDescription = contentDescription;
              handleSet(index, holder);
          }
      }
      
      

public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
          boolean isNew = getIcon(index, holder.getTag()) == null;
          super.setIcon(index, holder);
  
          if (isNew) {
              addSystemIcon(index, holder);
          } else {
              handleSet(index, holder);
          }
      }


private void addSystemIcon(int index, StatusBarIconHolder holder) {
          String slot = getSlotName(index);
          int viewIndex = getViewIndex(index, holder.getTag());
          boolean hidden = mIconHideList.contains(slot);
  
    //private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
    //回调StatusBarIconController中的IconManager的onIconAdded()
     mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, hidden, holder));
   }


private void handleSet(int index, StatusBarIconHolder holder) {
          int viewIndex = getViewIndex(index, holder.getTag());
   //private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
   //回调StatusBarIconController中的IconManager的onSetIconHolder()
    mIconGroups.forEach(l -> l.onSetIconHolder(viewIndex, holder));
 }



//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java)
 protected void onIconAdded(int index, String slot, boolean blocked,
                  StatusBarIconHolder holder) {
              addHolder(index, slot, blocked, holder);
          }
  
protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked,
                  StatusBarIconHolder holder) {
              // This is a little hacky, and probably regrettable, but just set `blocked` on any icon
              // that is in our blocked list, then we'll never see it
              if (mBlockList.contains(slot)) {
                  blocked = true;
              }
              switch (holder.getType()) {
                  case TYPE_ICON:
                      return addIcon(index, slot, blocked, holder.getIcon());
  
                  case TYPE_WIFI:
                      return addSignalIcon(index, slot, holder.getWifiState());
  
                  case TYPE_MOBILE:
                      return addMobileIcon(index, slot, holder.getMobileState());
              }
  
              return null;
  }

      
      
      

public void onSetIconHolder(int viewIndex, StatusBarIconHolder holder) {
             switch (holder.getType()) {
                 case TYPE_ICON:
                     onSetIcon(viewIndex, holder.getIcon());
                     return;
                 case TYPE_WIFI:
                     onSetSignalIcon(viewIndex, holder.getWifiState());
                     return;
  
                 case TYPE_MOBILE:
                     onSetMobileIcon(viewIndex, holder.getMobileState());
                 default:
                     break;
             }
}



@VisibleForTesting
          protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
                  StatusBarIcon icon) {
              StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
              view.set(icon);
              mGroup.addView(view, index, onCreateLayoutParams());
              return view;
          }
  
          @VisibleForTesting
          protected StatusBarWifiView addSignalIcon(int index, String slot, WifiIconState state) {
              StatusBarWifiView view = onCreateStatusBarWifiView(slot);
              view.applyWifiState(state);
              mGroup.addView(view, index, onCreateLayoutParams());
  
              if (mIsInDemoMode) {
                  mDemoStatusIcons.addDemoWifiView(state);
              }
              return view;
          }

状态栏图标列表配置在config.xml 中的 config_statusBarIcons 数组,在构造函数中执行初始化,StatusBar构造函数中会创建StatusBarIconController对象。

//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java)
  public StatusBarIconControllerImpl(
              Context context,
              CommandQueue commandQueue,
              DemoModeController demoModeController) {
          super(context.getResources().getStringArray(
                  com.android.internal.R.array.config_statusBarIcons));
          Dependency.get(ConfigurationController.class).addCallback(this);
  
          mContext = context;
  
          loadDimens();
  
          commandQueue.addCallback(this);
          Dependency.get(TunerService.class).addTunable(this, ICON_HIDE_LIST);
          demoModeController.addCallback(this);
      }

创建状态栏,通知栏,导航栏

public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {      
    //创建状态栏,导航栏,通知栏View
    makeStatusBarView(result);    
    //通过WindowManager.addView 添加通知栏窗口
    mNotificationShadeWindowController.attach();  
    //通过WindowManager.addView 添加状态栏窗口
    mStatusBarWindowController.attach();     }


创建状态栏,导航栏,通知栏View

     protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
          //创建状态栏,通知栏View
          inflateStatusBarWindow();
          mNotificationShadeWindowViewController.setService(this, mNotificationShadeWindowController);
          ...
       
 //通知图标区域控制器 
 mNotificationIconAreaController.setupShelf(mNotificationShelfController);
  //通知面板控制器,管理通知面板(下拉状态栏)的显示、交互与动画逻辑
  mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator);
          mNotificationPanelViewController.addExpansionListener(
                  this::dispatchPanelExpansionForKeyguardDismiss);
  
          
          //通过FragmentHostManager添加CollapsedStatusBarFragment加载状态栏布局
          FragmentHostManager.get(mPhoneStatusBarWindow)
                  .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
                      CollapsedStatusBarFragment statusBarFragment =
                              (CollapsedStatusBarFragment) fragment;
  
                      PhoneStatusBarView oldStatusBarView = mStatusBarView;
                      mStatusBarView = (PhoneStatusBarView) statusBarFragment.getView();
                      mStatusBarView.setBar(this);
                      mStatusBarView.setPanel(mNotificationPanelViewController);
                      mStatusBarView.setScrimController(mScrimController);
                      mStatusBarView.setExpansionChangedListeners(mExpansionChangedListeners);
  
                     
                      // status by calling mNotificationPanel.notifyBarPanelExpansionChanged().
                      if (mHeadsUpManager.hasPinnedHeadsUp()) {
                          mNotificationPanelViewController.notifyBarPanelExpansionChanged();
                      }
                      mStatusBarView.setBouncerShowing(mBouncerShowing);
                      if (oldStatusBarView != null) {
                          float fraction = oldStatusBarView.getExpansionFraction();
                          boolean expanded = oldStatusBarView.isExpanded();
                          mStatusBarView.panelExpansionChanged(fraction, expanded);
                      }
  
                    
                      
 ...  
                      mNotificationShadeWindowViewController.setStatusBarView(mStatusBarView);
                      checkBarModes();
                  }).getFragmentManager()
                  .beginTransaction()
                  .replace(R.id.status_bar_container,
                          new CollapsedStatusBarFragment(
                                  mOngoingCallController,
                                  mAnimationScheduler,
                                  mStatusBarLocationPublisher,
                                  mNotificationIconAreaController,
                                  mFeatureFlags,
                                  mStatusBarIconController,
                                  mKeyguardStateController,
                                  mNetworkController,
                                  mStatusBarStateController,
                                  this,
                                  mCommandQueue
                          ),
                          CollapsedStatusBarFragment.TAG)
                  .commit();
  

         
     ...
     
     mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
     //创建导航栏View
     createNavigationBar(result);
     
 
      ...
  
          // Set up the quick settings tile panel
          //下拉通知栏的QS面板加载
          final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame);

if (container != null) {
              FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
              ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
                      mExtensionController
                              .newExtension(QS.class)
                              .withPlugin(QS.class)
                   //创建一个默认的QSFragment实例,QSFragment会加载qs_panel.xml
                              .withDefault(this::createDefaultQSFragment)
                              .build());
              mBrightnessMirrorController = new BrightnessMirrorController(
                      mNotificationShadeWindowView,
                      mNotificationPanelViewController,
                      mNotificationShadeDepthControllerLazy.get(),
                      mBrightnessSliderFactory,
                      (visible) -> {
                          mBrightnessMirrorVisible = visible;
                          updateScrimController();
                      });
              fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
                  QS qs = (QS) f;
                  if (qs instanceof QSFragment) {
                      mQSPanelController = ((QSFragment) qs).getQSPanelController();
     //初始化亮度滑块,拖动亮度滑块时,在通知面板顶部会有一个“镜像”动画效果 mQSPanelController.setBrightnessMirror(mBrightnessMirrorController);
                  }
              });
          }
    
               
          
 
     ...
  

      }

创建状态栏,通知栏View


 private void inflateStatusBarWindow() {
         //构建通知栏View
         mNotificationShadeWindowView = mSuperStatusBarViewFactory.getNotificationShadeWindowView();
         StatusBarComponent statusBarComponent = mStatusBarComponentBuilder.get()
                  .statusBarWindowView(mNotificationShadeWindowView).build();
         mNotificationShadeWindowViewController = statusBarComponent
                  .getNotificationShadeWindowViewController();
          mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
         mNotificationShadeWindowViewController.setupExpandedStatusBar();
         mStatusBarWindowController = statusBarComponent.getStatusBarWindowController();
         ////构建状态栏View
         mPhoneStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView();
         mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController();
         statusBarComponent.getLockIconViewController().init();
  
      }

加载根布局super_notification_shade.xml,构建通知栏界面布局 NotificationShadeWindowView 的布局非常复杂,是整个下拉通知栏界面的根视图,它像一个容器,组合了多个关键子视图来实现丰富的功能。其主要组成部分包括:

  1. 背景与遮罩层:负责视觉层次和过渡效果。

    • BackDropView (@+id/backdrop) :用于显示通知或媒体应用的背景 artwork,在展开通知或播放音乐时提供沉浸式视觉背景。
    • ScrimView (@+id/scrim_behind) :位于通知面板后方的遮罩层,用于在拉下通知栏时,将桌面或应用界面变暗,突出前景内容。
    • ScrimView (@+id/scrim_notifications) :位于通知列表自身的遮罩层,用于在滚动通知列表时,在列表顶部或底部创建渐隐效果。
  2. 核心功能面板:承载了用户交互的主要内容。

    • LightRevealScrim (@+id/light_reveal_scrim) :一个特殊的遮罩,用于实现锁屏与AOD(Always On Display,息屏显示)之间的灯光揭示动画,创造平滑的视觉过渡效果。
    • <include layout="@layout/status_bar_expanded"/> :这是通知栏的核心,它包含了通知列表、快捷设置面板(QS Panel)等所有主要UI。默认是 invisible,只有在下拉时才会变为可见。
    • <include layout="@layout/brightness_mirror_container"/> :用于在快捷设置面板中显示亮度滑块的镜像布局。
  3. 锁屏与安全相关组件:

    • KeyguardMessageArea (@+id/keyguard_message_area) :在锁屏界面显示提示信息,如“滑动解锁”或充电状态等。
    • AuthRippleView (@+id/auth_ripple) :用于指纹或面部识别认证时的视觉反馈,会在认证成功或失败时产生波纹动画。
  4. 前景遮罩层:

    • ScrimView (@+id/scrim_in_front) :位于所有内容最前方的遮罩层,用于在显示锁屏验证界面(Bouncer)  时,模糊或遮盖后面的通知内容,保护隐私。

核心作用:通知面板与锁屏的载体

  • 通知面板的根视图:它是整个下拉通知栏的顶层容器。所有你下拉后看到的元素——通知列表、快捷开关、亮度滑块等,都作为子View包含在其中。
  • 锁屏界面的载体:与常规认知不同,锁屏界面(Keyguard)并非一个独立窗口,而是与通知面板共用 NotificationShadeWindowView。这意味着锁屏上的时钟、消息、解锁提示等,都是这个窗口的一部分。
  • 系统事件与交互的处理枢纽:它作为根视图,是触摸事件、按键事件的分发起点。例如,在AOD状态下双击屏幕,便是由它来捕获并唤醒设备的
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java

      public NotificationShadeWindowView getNotificationShadeWindowView() {
          if (mNotificationShadeWindowView != null) {
              return mNotificationShadeWindowView;
          }
  
          mNotificationShadeWindowView = (NotificationShadeWindowView)
                  mInjectionInflationController.injectable(
                  LayoutInflater.from(mContext)).inflate(R.layout.super_notification_shade,
                  /* root= */ null);
          if (mNotificationShadeWindowView == null) {
              throw new IllegalStateException(
                      "R.layout.super_notification_shade could not be properly inflated");
          }
  
          return mNotificationShadeWindowView;
      }
      

//frameworks/base/packages/SystemUI/res/layout/super_notification_shade.xml)
<com.android.systemui.statusbar.phone.NotificationShadeWindowView
     xmlns: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.BackDropView
             android: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.scrim.ScrimView
         android:id="@+id/scrim_behind"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:importantForAccessibility="no"
         sysui:ignoreRightInset="true"
         />
 
     <com.android.systemui.scrim.ScrimView
         android:id="@+id/scrim_notifications"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:importantForAccessibility="no"
         sysui:ignoreRightInset="true"
         />
 
     <com.android.systemui.statusbar.LightRevealScrim
             android:id="@+id/light_reveal_scrim"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:visibility="gone" />
 
     //通知面板
     <include layout="@layout/status_bar_expanded"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:visibility="invisible" />
 
     //亮度滑块
     <include layout="@layout/brightness_mirror_container" />
 
     <com.android.systemui.scrim.ScrimView
         android:id="@+id/scrim_in_front"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:importantForAccessibility="no"
         sysui:ignoreRightInset="true"
     />
 
     <!-- Keyguard messages -->
     <FrameLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="@dimen/status_bar_height"
         android:layout_gravity="top|center_horizontal"
         android:gravity="center_horizontal">
         <com.android.keyguard.KeyguardMessageArea
             android:id="@+id/keyguard_message_area"
             style="@style/Keyguard.TextView"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginTop="@dimen/keyguard_lock_padding"
             android:gravity="center"
             android:singleLine="true"
             android:ellipsize="marquee"
             android:focusable="true" />
     </FrameLayout>
 
     <com.android.systemui.biometrics.AuthRippleView
         android:id="@+id/auth_ripple"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:importantForAccessibility="no"
         sysui:ignoreRightInset="true"
     />
 </com.android.systemui.statusbar.phone.NotificationShadeWindowView>

super_status_bar.xml,是状态栏根布局, StatusBarWindowView 是状态栏UI的顶层容器,负责承载和显示状态栏相关的所有视觉元素 。status_bar.xml是状态栏实际的布局 ,顶层容器是 PhoneStatusBarView(继承自 FrameLayout)。它的内部主要分为三个区域:

  1. 左侧区域 (status_bar_left_side) :

    • Clock:显示时间的视图。
    • notification_icon_area:显示应用通知图标(如微信、短信图标)的容器。这些图标由 NotificationIconAreaController 动态填充。
    • ongoing_call_chip:正在进行的通话提示条。
  2. 中间区域 (centered_icon_area) :

    • 主要用于适配有刘海或挖孔的屏幕,在特定场景下(如自拍相机开启时)显示提示光点或摄像头指示器。
  3. 右侧区域 (system_icon_area) :

    • 包含 system_icons 布局,里面是信号强度、Wi-Fi、电池电量等系统级图标,由 StatusBarIconController 管理。
  4. 其他元素:

    • cutout_space_view:专门用来占据屏幕挖孔/刘海的位置,防止其他视图被遮挡。
    • emergency_cryptkeeper_text:加密状态或紧急情况下的文字提示(通常为 ViewStub,按需加载)。
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java

      public StatusBarWindowView getStatusBarWindowView() {
          if (mStatusBarWindowView != null) {
              return mStatusBarWindowView;
          }
  
          mStatusBarWindowView =
                  (StatusBarWindowView) mInjectionInflationController.injectable(
                  LayoutInflater.from(mContext)).inflate(R.layout.super_status_bar,
                  /* root= */ null);
          if (mStatusBarWindowView == null) {
              throw new IllegalStateException(
                      "R.layout.super_status_bar could not be properly inflated");
          }
          return mStatusBarWindowView;
      }
      
      
 
 //frameworks/base/packages/SystemUI/res/layout/super_status_bar.xml)
 <com.android.systemui.statusbar.phone.StatusBarWindowView
     xmlns: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">
 
     <FrameLayout
         //用于处理应用启动动画
         android:id="@+id/status_bar_launch_animation_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
     <FrameLayout
         //用于加载真正的状态栏
         android:id="@+id/status_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="@drawable/system_bar_background" />
 </com.android.systemui.statusbar.phone.StatusBarWindowView>
 
 
 
 
//frameworks/base/packages/SystemUI/res/layout/status_bar.xml
<com.android.systemui.statusbar.phone.PhoneStatusBarView
     xmlns: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:orientation="vertical"
     android:focusable="false"
     android:descendantFocusability="afterDescendants"
     android:accessibilityPaneTitle="@string/status_bar"
     >
 
     <ImageView
         android: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:paddingTop="@dimen/status_bar_padding_top"
         android:orientation="horizontal"
         >
         <FrameLayout
             android:layout_height="match_parent"
             android:layout_width="0dp"
             android:layout_weight="1">
 
             <include layout="@layout/heads_up_status_bar_layout" />
 
             <!-- The alpha of the left side is controlled by PhoneStatusBarTransitions, and the
              individual views are controlled by StatusBarManager disable flags DISABLE_CLOCK and
              DISABLE_NOTIFICATION_ICONS, respectively -->
             <LinearLayout
             //左侧图标区域:显示通知,时间
                 android:id="@+id/status_bar_left_side"
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
                 android:clipChildren="false"
             >
                 <ViewStub
                     android:id="@+id/operator_name"
                     android:layout_width="wrap_content"
                     android:layout_height="match_parent"
                     android:layout="@layout/operator_name" />
 
                 <com.android.systemui.statusbar.policy.Clock
                     android: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"
                 />
               
                //正在通话提示条
                 <include layout="@layout/ongoing_call_chip" />
 
                 <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
                 //显示应用通知图标区域
                     android: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>
 
         <!-- Space should cover the notch (if it exists) and let other views lay out around it -->
         <android.widget.Space
             android:id="@+id/cutout_space_view"
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:gravity="center_horizontal|center_vertical"
         />
 
         <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
         //中间图标区域
             android:id="@+id/centered_icon_area"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:orientation="horizontal"
             android:clipChildren="false"
             android:gravity="center_horizontal|center_vertical"/>
 
         <com.android.keyguard.AlphaOptimizedLinearLayout 
         //右侧系统图标区域:信号强度、Wi-Fi、电池电量等系统级图标
         android: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>
 
     <ViewStub
         android: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>

通过WindowManager.addView 添加通知栏窗口

//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java)
     public void attach() {
      
          mLp = new LayoutParams(
                  ViewGroup.LayoutParams.MATCH_PARENT,
                  ViewGroup.LayoutParams.MATCH_PARENT,
                  LayoutParams.TYPE_NOTIFICATION_SHADE,
                  LayoutParams.FLAG_NOT_FOCUSABLE
                          | LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                          | LayoutParams.FLAG_SPLIT_TOUCH
                          | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                          | LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                  PixelFormat.TRANSLUCENT);
          mLp.token = new Binder();
          mLp.gravity = Gravity.TOP;
          mLp.setFitInsetsTypes(0 /* types */);
          mLp.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
          mLp.setTitle("NotificationShade");
          mLp.packageName = mContext.getPackageName();
          mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
  
          // We use BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE here, however, there is special logic in
          // window manager which disables the transient show behavior.
          // TODO: Clean this up once that behavior moves into the Shell.
          mLp.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
          mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
  
          mWindowManager.addView(mNotificationShadeView, mLp);
          mLpChanged.copyFrom(mLp);
          onThemeChanged();
  
          // Make the state consistent with KeyguardViewMediator#setupLocked during initialization.
          if (mKeyguardViewMediator.isShowingAndNotOccluded()) {
              setKeyguardShowing(true);
          }
      }

通过WindowManager.addView 添加状态栏窗口

//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java)
  public void attach() {


          mLp = new WindowManager.LayoutParams(
                  ViewGroup.LayoutParams.MATCH_PARENT,
                  mBarHeight,
                  WindowManager.LayoutParams.TYPE_STATUS_BAR,
                  WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                          | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                          | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                  PixelFormat.TRANSLUCENT);
          mLp.privateFlags |= PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
          mLp.token = new Binder();
          mLp.gravity = Gravity.TOP;
          mLp.setFitInsetsTypes(0 /* types */);
          mLp.setTitle("StatusBar");
          mLp.packageName = mContext.getPackageName();
          mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
  
          mWindowManager.addView(mStatusBarView, mLp);
          mLpChanged.copyFrom(mLp);
  
          mContentInsetsProvider.addCallback(this::calculateStatusBarLocationsForAllRotations);
          calculateStatusBarLocationsForAllRotations();
      }

CollapsedStatusBarFragment整体结构:

  • StatusBar(大总管) :StatusBar 在 makeStatusBarView() 方法中创建并添加 CollapsedStatusBarFragment 到布局容器中。
  • StatusBarIconController(中央调度室) :CollapsedStatusBarFragment 会向它注册 DarkIconManager,从而接收图标更新指令。
  • PhoneStatusBarPolicy(策略制定者) :它不直接与 CollapsedStatusBarFragment 交互,而是通过 StatusBarIconController 下发指令,最终由 CollapsedStatusBarFragment 中的 DarkIconManager 执行。

生命周期与关键方法

  • onCreateView() :在Fragment创建视图时调用,核心工作是加载 status_bar.xml 布局文件。
  • onViewCreated() :在视图创建完成后调用,会找到 status_bar.xml 中定义的各个视图元素(如 mSystemIconArea、mClockView 等)。
  • initNotificationIconArea() :专门用于初始化左侧通知图标区域的方法。
  • showSystemIconArea() / hideSystemIconArea() :提供直接控制系统图标显示或隐藏的方法。
  • disable() :作为 CommandQueue.Callbacks 接口的方法,用于接收系统“禁用”标志,并执行相应逻辑。
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java)
 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
              Bundle savedInstanceState) {
          return inflater.inflate(R.layout.status_bar, container, false);
      }


public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
          super.onViewCreated(view, savedInstanceState);
          mStatusBar = (PhoneStatusBarView) view;
          View contents = mStatusBar.findViewById(R.id.status_bar_contents);
          contents.addOnLayoutChangeListener(mStatusBarLayoutListener);
          updateStatusBarLocation(contents.getLeft(), contents.getRight());
          ...
          //DarkIconManager实现了IconManager
          mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons), mFeatureFlags);
          mDarkIconManager.setShouldLog(true);
          mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_volume));
          mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
          mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
          mDarkIconManager.setBlockList(mBlockedIcons);
          //
          mStatusBarIconController.addIconGroup(mDarkIconManager);
          mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
          mClockView = mStatusBar.findViewById(R.id.clock);
          mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip);
          showSystemIconArea(false);
          showClock(false);
          initEmergencyCryptkeeperText();
          initOperatorName();
          initNotificationIconArea();
          mAnimationScheduler.addCallback(this);
}

      
      
 
//frameworks/base/packages/SystemUI/res/layout/status_bar.xml
<com.android.systemui.statusbar.phone.PhoneStatusBarView
     xmlns: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:orientation="vertical"
     android:focusable="false"
     android:descendantFocusability="afterDescendants"
     android:accessibilityPaneTitle="@string/status_bar"
     >
 
     <ImageView
         android: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:paddingTop="@dimen/status_bar_padding_top"
         android:orientation="horizontal"
         >
         <FrameLayout
             android:layout_height="match_parent"
             android:layout_width="0dp"
             android:layout_weight="1">
 
             <include layout="@layout/heads_up_status_bar_layout" />
 
             <!-- The alpha of the left side is controlled by PhoneStatusBarTransitions, and the
              individual views are controlled by StatusBarManager disable flags DISABLE_CLOCK and
              DISABLE_NOTIFICATION_ICONS, respectively -->
             <LinearLayout
                 android:id="@+id/status_bar_left_side"
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
                 android:clipChildren="false"
             >
                 <ViewStub
                     android:id="@+id/operator_name"
                     android:layout_width="wrap_content"
                     android:layout_height="match_parent"
                     android:layout="@layout/operator_name" />
 
                 <com.android.systemui.statusbar.policy.Clock
                     android: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"
                 />
 
                 <include layout="@layout/ongoing_call_chip" />
 
                 <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
                     android: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>
 
         <!-- Space should cover the notch (if it exists) and let other views lay out around it -->
         <android.widget.Space
             android:id="@+id/cutout_space_view"
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:gravity="center_horizontal|center_vertical"
         />
 
         <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
             android:id="@+id/centered_icon_area"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:orientation="horizontal"
             android:clipChildren="false"
             android:gravity="center_horizontal|center_vertical"/>
 
         <com.android.keyguard.AlphaOptimizedLinearLayout android: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>
 
     <ViewStub
         android: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>

PhoneStatusBarView 承担着多重职责:

  • 状态栏的UI容器:它是状态状态栏所有UI元素的直接父容器。
  • 交互事件的处理者:它重写了父类 PanelBar 的方法(如 onPanelPeeked()),负责处理用户的触摸事件,并触发相应的逻辑(如下拉展开通知面板)。
  • 与控制器(StatusBar)的桥梁:它持有 StatusBar 的引用(mBar),作为视图层与控制器层通信的桥梁。例如,当面板被拖拽时,它会调用 mBar.makeExpandedVisible() 来显示展开后的通知面板。

与其他核心组件的关系

PhoneStatusBarView 在SystemUI的视图体系中,与多个组件协同工作:

  • StatusBar:控制器。SystemUI 的核心服务之一,负责整体状态栏的逻辑控制。PhoneStatusBarView 通过 setBar() 方法与之关联,两者互相持有引用。
  • StatusBarWindowView:根布局容器。它是整个状态栏窗口的根视图。PhoneStatusBarView 作为其子视图存在。
  • NotificationShadeWindowView:通知面板(展开状态)的根视图。它与 StatusBarWindowView 是平级关系,是两个独立的系统窗口。PhoneStatusBarView 负责触发它的显示(如下拉时)。
  • NotificationPanelView:通知面板的具体内容视图。
  • CollapsedStatusBarFragment:UI加载器。这个 Fragment 负责将 status_bar.xml 布局文件(即 PhoneStatusBarView)加载到 StatusBarWindowView 中。