android16 SystemUI之StatusBar启动

读取SystemUI核心组件(不再通过config.xml):

  • SystemUIService调用SystemUIApplication的startSystemUserServicesIfNeeded()
  • 通过 Dagger 组件 (mSysUIComponent) 获取所有标注好的 CoreStartable 实现类。
  • 通过 Dagger 的 @Binds 注解自动注入到 getStartables() 集合中。
scss 复制代码
//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@Override
public void onCreate() {
    super.onCreate();
   //android12调用的是startServicesIfNeeded
   // Start all of SystemUI
   ((SystemUIApplication) getApplication()).startSystemUserServicesIfNeeded();
    ...
    
}


//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java)

 public void startSystemUserServicesIfNeeded() {
          if (!shouldStartSystemUserServices()) {
             
              return;  
          }
          //SystemUIInitializer mInitializer;
          final String vendorComponent = mInitializer.getVendorComponent(getResources());
  
          // Sort the startables so that we get a deterministic ordering.
          // TODO: make #start idempotent and require users of CoreStartable to call it.
          Map<Class<?>, Provider<CoreStartable>> sortedStartables = new TreeMap<>(
                  Comparator.comparing(Class::getName));
          //全局核心服务
          sortedStartables.putAll(mSysUIComponent.getStartables());
          //用户核心服务
          sortedStartables.putAll(mSysUIComponent.getPerUserStartables());
          startServicesIfNeeded(
                  sortedStartables, "StartServices", vendorComponent);
      }

真正启动组件:

  • 遍历 sortedStartables 列表,依次调用每个 CoreStartablestart() 方法。
  • 处理传入的 vendorComponent 字符串,通过反射机制实例化并启动这个厂商自定义组件。
ini 复制代码
//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java)
 private void startServicesIfNeeded(
              Map<Class<?>, Provider<CoreStartable>> startables,
              String metricsPrefix,
              String vendorComponent) {
          if (mServicesStarted) {
              return;
          }
          mServices = new CoreStartable[startables.size() + (vendorComponent == null ? 0 : 1)];
  
          if (!mBootCompleteCache.isBootComplete()) {
              // check to see if maybe it was already completed long before we began
              // see ActivityManagerService.finishBooting()
              if ("1".equals(getRootComponent().getSystemPropertiesHelper()
                      .get("sys.boot_completed"))) {
                  mBootCompleteCache.setBootComplete();
                  if (DEBUG) {
                      Log.v(TAG, "BOOT_COMPLETED was already sent");
                  }
              }
          }
  
          DumpManager dumpManager = mSysUIComponent.createDumpManager();
  
          Log.v(TAG, "Starting SystemUI services for user " +
                  Process.myUserHandle().getIdentifier() + ".");
          TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
                  Trace.TRACE_TAG_APP);
          log.traceBegin(metricsPrefix);
  
          HashSet<Class<?>> startedStartables = new HashSet<>();
  
          // Perform a form of topological sort:
          // 1) Iterate through a queue of all non-started startables
          //   If the startable has all of its dependencies met
          //     - start it
          //   Else
          //     - enqueue it for the next iteration
          // 2) If anything was started and the "next" queue is not empty, loop back to 1
          // 3) If we're done looping and there are any non-started startables left, throw an error.
          //
          // This "sort" is not very optimized. We assume that most CoreStartables don't have many
          // dependencies - zero in fact. We assume two or three iterations of this loop will be
          // enough. If that ever changes, it may be worth revisiting.
  
          log.traceBegin("Topologically start Core Startables");
          boolean startedAny = false;
          ArrayDeque<Map.Entry<Class<?>, Provider<CoreStartable>>> queue;
          ArrayDeque<Map.Entry<Class<?>, Provider<CoreStartable>>> nextQueue =
                  new ArrayDeque<>(startables.entrySet());
          int numIterations = 0;
  
          int serviceIndex = 0;
  
          do {
              startedAny = false;
              queue = nextQueue;
              nextQueue = new ArrayDeque<>(startables.size());
  
              while (!queue.isEmpty()) {
                  Map.Entry<Class<?>, Provider<CoreStartable>> entry = queue.removeFirst();
  
                  Class<?> cls = entry.getKey();
                  Set<Class<? extends CoreStartable>> deps =
                          mSysUIComponent.getStartableDependencies().get(cls);
                  if (deps == null || startedStartables.containsAll(deps)) {
                      String clsName = cls.getName();
                      int i = serviceIndex;  // Copied to make lambda happy.
                      timeInitialization(
                              clsName,
                              () -> mServices[i] = startStartable(clsName, entry.getValue()),
                              log,
                              metricsPrefix);
                      startedStartables.add(cls);
                      startedAny = true;
                      serviceIndex++;
                  } else {
                      nextQueue.add(entry);
                  }
              }
              numIterations++;
          } while (startedAny && !nextQueue.isEmpty()); // if none were started, stop.
  
          if (!nextQueue.isEmpty()) { // If some startables were left over, throw an error.
              while (!nextQueue.isEmpty()) {
                  Map.Entry<Class<?>, Provider<CoreStartable>> entry = nextQueue.removeFirst();
                  Class<?> cls = entry.getKey();
                  Set<Class<? extends CoreStartable>> deps =
                          mSysUIComponent.getStartableDependencies().get(cls);
                  StringJoiner stringJoiner = new StringJoiner(", ");
                  for (Class<? extends CoreStartable> c : deps) {
                      if (!startedStartables.contains(c)) {
                          stringJoiner.add(c.getName());
                      }
                  }
                  Log.e(TAG, "Failed to start " + cls.getName()
                          + ". Missing dependencies: [" + stringJoiner + "]");
              }
  
              throw new RuntimeException("Failed to start all CoreStartables. Check logcat!");
          }
          Log.i(TAG, "Topological CoreStartables completed in " + numIterations + " iterations");
          log.traceEnd();
  
          if (vendorComponent != null) {
              timeInitialization(
                      vendorComponent,
                      () -> mServices[mServices.length - 1] =
                              startAdditionalStartable(vendorComponent),
                      log,
                      metricsPrefix);
          }
  
          for (serviceIndex = 0; serviceIndex < mServices.length; serviceIndex++) {
              final CoreStartable service = mServices[serviceIndex];
              if (mBootCompleteCache.isBootComplete()) {
                  notifyBootCompleted(service);
              }
  
              if (service.isDumpCritical()) {
                  dumpManager.registerCriticalDumpable(service);
              } else {
                  dumpManager.registerNormalDumpable(service);
              }
          }
          mSysUIComponent.getInitController().executePostInitTasks();
          log.traceEnd();
  
          mServicesStarted = true;
  }

android16中StatusBar没有了,变成了CentralSurfacesImpl,不再继承SystemUI,改成了实现CoreStartable

启动状态栏,通知栏,导航栏

CentralSurfacesImpl 复制代码
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java)

 
public void start() {

  
          
  
     
          mBarService = IStatusBarService.Stub.asInterface(
                  ServiceManager.getService(Context.STATUS_BAR_SERVICE));
  
          mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
          mWallpaperSupported = mWallpaperManager.isWallpaperSupported();
  
          RegisterStatusBarResult result = null;
          if (!StatusBarConnectedDisplays.isEnabled()) {
              try {
              //注册CommandQueue到StatusBarManagerService
                  result = mBarService.registerStatusBar(mCommandQueue);
              } catch (RemoteException ex) {
                  ex.rethrowFromSystemServer();
              }
          }
         
         //创建状态栏,导航栏,通知栏
          createAndAddWindows(result);
          //初始化通知栏状态
          setUpPresenter();
  
          // When the StatusBarConnectedDisplays flag is enabled, this logic will be done in
          // StatusBarOrchestrator
          if (!StatusBarConnectedDisplays.isEnabled()) {
              if ((result.mTransientBarTypes & WindowInsets.Type.statusBars()) != 0) {
                  mStatusBarModeRepository.getDefaultDisplay().showTransient();
              }
              mCommandQueueCallbacks.onSystemBarAttributesChanged(
                      mDisplayId,
                      result.mAppearance,
                      result.mAppearanceRegions,
                      result.mNavbarColorManagedByIme,
                      result.mBehavior,
                      result.mRequestedVisibleTypes,
                      result.mPackageName,
                      result.mLetterboxDetails);
  
              // StatusBarManagerService has a back up of IME token and it's restored here.
              mCommandQueueCallbacks.setImeWindowStatus(
                      mDisplayId,
                      result.mImeWindowVis,
                      result.mImeBackDisposition,
                      result.mShowImeSwitcher);
  
              // 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));
              }
  

  
          if (mWallpaperSupported) {
              IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
                      ServiceManager.getService(Context.WALLPAPER_SERVICE));
              try {
                  wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */);
              } catch (RemoteException e) {
                  // Just pass, nothing critical.
              }
          }
  
          // end old BaseStatusBar.start().
  
          // Lastly, call to the icon policy to install/update all the icons.
          //初始化状态栏图标 PhoneStatusBarPolicy mIconPolicy
          mIconPolicy.init();
  
        
  

          startKeyguard();
  
          mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
          mDozeServiceHost.initialize(
                  this,
                  mStatusBarKeyguardViewManager,
                  getNotificationShadeWindowViewController(),
                  mAmbientIndicationContainer);


  
          mStartingSurfaceOptional.ifPresent(startingSurface -> startingSurface.setSysuiProxy(
                  (requestTopUi, componentTag) -> mMainExecutor.execute(() ->
                          mNotificationShadeWindowController.setRequestTopUi(
                                  requestTopUi, componentTag))));
}

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

StatusBarManagerService 复制代码
//frameworks/base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java)
 
  public RegisterStatusBarResult registerStatusBar(IStatusBar bar) {
          enforceStatusBarService();
          enforceValidCallingUser();
  
          Slog.i(TAG, "registerStatusBar bar=" + bar);
          mBar = bar;
          mDeathRecipient.linkToDeath();
          notifyBarAttachChanged();
          final ArrayMap<String, StatusBarIcon> icons;
          synchronized (mIcons) {
              icons = new ArrayMap<>(mIcons);
          }
          synchronized (mLock) {
              final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
              return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
                      state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis,
                      state.mImeBackDisposition, state.mShowImeSwitcher,
                      gatherDisableActionsLocked(mCurrentUserId, 2),
                      state.mNavbarColorManagedByIme, state.mBehavior, state.mRequestedVisibleTypes,
                      state.mPackageName, state.mTransientBarTypes, state.mLetterboxDetails);
          }
}

PhoneStatusBarPolicy初始化状态栏图标入口

  • PhoneStatusBarPolicy:决定了哪些图标应在开机时加载到状态栏。它会根据系统状态(如蓝牙是否开启、是否有闹钟等)来显示和隐藏系统图标。
  • StatusBar :SystemUI的主入口,负责初始化整体布局并实例。化 PhoneStatusBarPolicy
  • StatusBarManagerService:系统服务,负责接收并管理来自各个应用的图标更新请求。
  • IconManager :实际负责将 StatusBarIconView 添加到状态栏布局中。
  • StatusBarIconView:负责单个图标的具体显示和更。
  • StatusBarIconControllerImpl :作为中间层,将 PhoneStatusBarPolicy 的控制指令分发到具体的 IconManager 去执行。

StatusBarIconController实现类StatusBarIconControllerImpl,mIconController在构造函数中创建,创建的时候就会去加载配置的系统状态栏图标

scss 复制代码
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java)
    public void init() {
          ...
          // TTY status
          updateTTY();
  
          // bluetooth status
          updateBluetooth();
  
          // Alarm clock
          //private final StatusBarIconController mIconController;
          //设置图标
          mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
          mIconController.setIconVisibility(mSlotAlarmClock, false);
          ...
         
          mCommandQueue.addCallback(this);
      }

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

scss 复制代码
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
public void setIcon(String slot, int resourceId, CharSequence contentDescription) {

setResourceIconInternal(
                  slot,
                  Icon.createWithResource(mContext, resourceId),
                  /* preloadedIcon= */ null,
                  contentDescription,
                  StatusBarIcon.Type.SystemIcon,
                  StatusBarIcon.Shape.WRAP_CONTENT);

   
}
      
        

private void setResourceIconInternal(String slot, Icon resourceIcon,
              @Nullable Drawable preloadedIcon, CharSequence contentDescription,
              StatusBarIcon.Type type, StatusBarIcon.Shape shape) {
          checkArgument(resourceIcon.getType() == Icon.TYPE_RESOURCE,
                  "Expected Icon of TYPE_RESOURCE, but got " + resourceIcon.getType());
          String resPackage = resourceIcon.getResPackage();
          if (TextUtils.isEmpty(resPackage)) {
              resPackage = mContext.getPackageName();
          }
  
          StatusBarIconHolder holder = mStatusBarIconList.getIconHolder(slot, 0);
          if (holder == null) {
              StatusBarIcon icon = new StatusBarIcon(UserHandle.SYSTEM, resPackage,
                      resourceIcon, /* iconLevel= */ 0, /* number=*/ 0,
                      contentDescription, type, shape);
              icon.preloadedIcon = preloadedIcon;
              holder = StatusBarIconHolder.fromIcon(icon);
              setIcon(slot, holder);
          } else {
              holder.getIcon().pkg = resPackage;
              holder.getIcon().icon = resourceIcon;
              holder.getIcon().contentDescription = contentDescription;
              holder.getIcon().type = type;
              holder.getIcon().shape = shape;
              holder.getIcon().preloadedIcon = preloadedIcon;
              handleSet(slot, holder);
          }
 }


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

}



   

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




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



//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java.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;
          }
          return switch (holder.getType()) {
              case TYPE_ICON -> addIcon(index, slot, blocked, holder.getIcon());
              case TYPE_WIFI_NEW -> addNewWifiIcon(index, slot);
              case TYPE_MOBILE_NEW -> addNewMobileIcon(index, slot, holder.getTag());
              case TYPE_BINDABLE ->
                  // Safe cast, since only BindableIconHolders can set this tag on themselves
                      addBindableIcon((BindableIconHolder) holder, index);
              default -> null;
          };
      }


      
      
      



 public void onSetIconHolder(int viewIndex, StatusBarIconHolder holder) {
          switch (holder.getType()) {
              case TYPE_ICON:
                  onSetIcon(viewIndex, holder.getIcon());
                  return;
              case TYPE_MOBILE_NEW:
              case TYPE_WIFI_NEW:
              case TYPE_BINDABLE:
                  // Nothing, the new icons update themselves
                  return;
              default:
                  break;
          }
      }

          
 
public void onSetIcon(int viewIndex, StatusBarIcon icon) {
          StatusBarIconView view = (StatusBarIconView) mGroup.getChildAt(viewIndex);
          if (ModesUiIcons.isEnabled()) {
              ViewGroup.LayoutParams current = view.getLayoutParams();
              ViewGroup.LayoutParams desired = onCreateLayoutParams(icon.shape);
              if (desired.width != current.width || desired.height != current.height) {
                  view.setLayoutParams(desired);
              }
          }
          view.set(icon);
}
  

状态栏图标列表配置在config.xml 中的 config_statusBarIcons 数组,StatusBarIconControllerImpl的构造函数中初始化StatusBarIconList的时候通过Dagger注入

scss 复制代码
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java)
  
@Inject
public StatusBarIconControllerImpl(
              Context context,
              CommandQueue commandQueue,
              DemoModeController demoModeController,
              ConfigurationController configurationController,
              TunerService tunerService,
              DumpManager dumpManager,
              StatusBarIconList statusBarIconList,
              StatusBarPipelineFlags statusBarPipelineFlags,
              BindableIconsRegistry modernIconsRegistry
      ) {
          mStatusBarIconList = statusBarIconList;
          mContext = context;
          mStatusBarPipelineFlags = statusBarPipelineFlags;
  
          configurationController.addCallback(this);
          commandQueue.addCallback(mCommandQueueCallbacks);
          tunerService.addTunable(this, ICON_HIDE_LIST);
          demoModeController.addCallback(this);
          dumpManager.registerDumpable(getClass().getSimpleName(), this);
  
          addModernBindableIcons(modernIconsRegistry);
      }

 }
 
//状态栏图标列表
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java

@Provides
      @SysUISingleton
      static StatusBarIconList provideStatusBarIconList(Context context) {
          return new StatusBarIconList(
                  context.getResources().getStringArray(
                          com.android.internal.R.array.config_statusBarIcons));
 }

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

less 复制代码
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java)
public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {       //1.创建状态栏,导航栏,通知栏View
    makeStatusBarView(result);    
    //2.通过WindowManager.addView 添加通知栏窗口
    mNotificationShadeWindowController.attach();  
    //当未启用新多屏功能时,通过 Store 获取默认显示屏的控制器
    //3.通过WindowManager.addView 添加状态栏窗口
   if (!StatusBarConnectedDisplays.isEnabled()) {
              mStatusBarWindowControllerStore.getDefaultDisplay().attach();
          } 
    }

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

scss 复制代码
 //frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java)
protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
          ...
  
          setUpShade();
          getNotificationShadeWindowView().setOnTouchListener(getStatusBarWindowTouchListener());
          mWallpaperController.setRootView(getNotificationShadeWindowView());
  
          mDemoModeController.addCallback(mDemoModeCallback);
          // When the StatusBarConnectedDisplays flag is enabled, this logic will be done in
          // StatusBarOrchestrator.
          if (!StatusBarConnectedDisplays.isEnabled()) {
              mJavaAdapter.alwaysCollectFlow(
                      mStatusBarModeRepository.getDefaultDisplay().isTransientShown(),
                      this::onTransientShownChanged);
              mJavaAdapter.alwaysCollectFlow(
                      mStatusBarModeRepository.getDefaultDisplay().getStatusBarMode(),
                      this::updateBarMode);
          }
          mCommandQueueCallbacks = mCommandQueueCallbacksLazy.get();
          mCommandQueue.addCallback(mCommandQueueCallbacks);
  
          // TODO: Deal with the ugliness that comes from having some of the status bar broken out
          // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
          ShadeExpansionChangeEvent currentState =
                  mShadeExpansionStateManager.addExpansionListener(mWakeUpCoordinator);
          mWakeUpCoordinator.onPanelExpansionChanged(currentState);
  
          // When the StatusBarConnectedDisplays flag is enabled, all this logic will be done in
          // StatusBarOrchestrator.
          if (!StatusBarConnectedDisplays.isEnabled()) {
              // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
              mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class);
              mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
  
              // Set up CollapsedStatusBarFragment and PhoneStatusBarView
              mStatusBarInitializer.setStatusBarViewUpdatedListener(
                      (statusBarViewController, statusBarTransitions) -> {
  
                          mPhoneStatusBarViewController = statusBarViewController;
                          mStatusBarTransitions = statusBarTransitions;
                          getNotificationShadeWindowViewController()
                                  .setStatusBarViewController(mPhoneStatusBarViewController);
                          // Ensure we re-propagate panel expansion values to the panel controller and
                          // any listeners it may have, such as PanelBar. This will also ensure we
                          // re-display the notification panel if necessary (for example, if
                          // a heads-up notification was being displayed and should continue being
                          // displayed).
                          mShadeSurface.updateExpansionAndVisibility();
                          setBouncerShowingForStatusBarComponents(mBouncerShowing);
                          checkBarModes();
                      });
          }
          if (!StatusBarRootModernization.isEnabled() && !StatusBarConnectedDisplays.isEnabled()) {
              // When the flag is on, we register the fragment as a core startable and this is not
              // needed
              mStatusBarInitializer.initializeStatusBar();
          }
  
          mShadeTouchableRegionManager.setup(getNotificationShadeWindowView());
  
          if (!StatusBarConnectedDisplays.isEnabled()) {
              createNavigationBar(result);
          }
  
          mAmbientIndicationContainer = getNotificationShadeWindowView().findViewById(
                  R.id.ambient_indication_container);
  
          // When the StatusBarConnectedDisplays flag is enabled, all this logic will be done in
          // StatusBarOrchestrator.
          if (!StatusBarConnectedDisplays.isEnabled()) {
              mAutoHideController.setStatusBar(
                      new AutoHideUiElement() {
                          @Override
                          public void synchronizeState() {
                              checkBarModes();
                          }
  
                          @Override
                          public boolean shouldHideOnTouch() {
                              return !mRemoteInputManager.isRemoteInputActive();
                          }
  
                          @Override
                          public boolean isVisible() {
                              return isTransientShown();
                          }
  
                          @Override
                          public void hide() {
                              mStatusBarModeRepository.getDefaultDisplay().clearTransient();
                          }
                      });
          }
  
          ScrimView scrimBehind = getNotificationShadeWindowView().findViewById(R.id.scrim_behind);
          ScrimView notificationsScrim = getNotificationShadeWindowView()
                  .findViewById(R.id.scrim_notifications);
          ScrimView scrimInFront = getNotificationShadeWindowView().findViewById(R.id.scrim_in_front);
  
          mScrimController.setScrimVisibleListener(scrimsVisible -> {
              mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible);
          });
          mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront);
  
          mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> {
              Runnable updateOpaqueness = () -> {
                  mNotificationShadeWindowController.setLightRevealScrimOpaque(
                          mLightRevealScrim.isScrimOpaque());
                  mScreenOffAnimationController
                          .onScrimOpaqueChanged(mLightRevealScrim.isScrimOpaque());
              };
              if (opaque) {
                  // Delay making the view opaque for a frame, because it needs some time to render
                  // otherwise this can lead to a flicker where the scrim doesn't cover the screen
                  mLightRevealScrim.post(updateOpaqueness);
              } else {
                  updateOpaqueness.run();
              }
          });
  
          mScreenOffAnimationController.initialize(this, mShadeSurface, mLightRevealScrim);
  
          if (!SceneContainerFlag.isEnabled()) {
              mShadeSurface.initDependencies(
                      this,
                      mGestureRec,
                      mShadeController::makeExpandedInvisible,
                      mHeadsUpManager);
          }
  
          // Set up the quick settings tile panel
          final View container = getNotificationShadeWindowView().findViewById(R.id.qs_frame);
          if (container != null && !SceneContainerFlag.isEnabled()) {
              FragmentHostManager fragmentHostManager =
                      mFragmentService.getFragmentHostManager(container);
              ExtensionFragmentListener.attachExtensonToFragment(
                      mFragmentService,
                      container,
                      QS.TAG,
                      R.id.qs_frame,
                      mExtensionController
                              .newExtension(QS.class)
                              .withPlugin(QS.class)
                              .withDefault(this::createDefaultQSFragment)
                              .build());
              mBrightnessMirrorController = new BrightnessMirrorController(
                      getNotificationShadeWindowView(),
                      mShadeSurface,
                      mNotificationShadeDepthControllerLazy.get(),
                      mBrightnessSliderFactory,
                      this::setBrightnessMirrorShowing);
              fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
                  QS qs = (QS) f;
                  if (qs instanceof QSFragmentLegacy) {
                      QSFragmentLegacy qsFragment = (QSFragmentLegacy) qs;
                      mQSPanelController = qsFragment.getQSPanelController();
                      qsFragment.setBrightnessMirrorController(mBrightnessMirrorController);
                  }
              });
          }
  
          mReportRejectedTouch = getNotificationShadeWindowView()
                  .findViewById(R.id.report_rejected_touch);
          if (mReportRejectedTouch != null) {
              updateReportRejectedTouchVisibility();
              mReportRejectedTouch.setOnClickListener(v -> {
                  Uri session = mFalsingManager.reportRejectedTouch();
                  if (session == null) { return; }
  
                  StringWriter message = new StringWriter();
                  message.write("Build info: ");
                  message.write(SystemProperties.get("ro.build.description"));
                  message.write("\nSerial number: ");
                  message.write(SystemProperties.get("ro.serialno"));
                  message.write("\n");
  
                  
  
          if (!mPowerManager.isInteractive()) {
              mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
          }
          mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
                  "sysui:GestureWakeLock");
  
          // receive broadcasts
          registerBroadcastReceiver();
  
          // listen for USER_SETUP_COMPLETE setting (per-user)
          mDeviceProvisionedController.addCallback(mUserSetupObserver);
          mUserSetupObserver.onUserSetupChanged();
  
          // disable profiling bars, since they overlap and clutter the output on app windows
          ThreadedRenderer.overrideProperty("disableProfileBars", "true");
  
          // Private API call to make the shadows look better for Recents
          ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
      }

       
       

//https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
 private void setUpShade() {
          
          mNotificationShadeWindowController.fetchWindowRootView();
          getNotificationShadeWindowViewController().setupExpandedStatusBar();
          getNotificationShadeWindowViewController().setupCommunalHubLayout();
      }
      
      
      

//https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
 public void fetchWindowRootView() {
309          WindowRootViewComponent component = mWindowRootViewComponentFactory.create();
310          mWindowRootView = component.getWindowRootView();
311          collectFlow(
312                  mWindowRootView,
313                  mShadeInteractorLazy.get().isAnyExpanded(),
314                  this::onShadeOrQsExpanded
315          );
316          collectFlow(
317                  mWindowRootView,
318                  mShadeInteractorLazy.get().isQsExpanded(),
319                  this::onQsExpansionChanged
320          );
321          collectFlow(
322                  mWindowRootView,
323                  mCommunalInteractor.get().isCommunalVisible(),
324                  this::onCommunalVisibleChanged
325          );
326  
327          if (!SceneContainerFlag.isEnabled() && Flags.useTransitionsForKeyguardOccluded()) {
328              collectFlow(
329                      mWindowRootView,
330                      mNotificationShadeWindowModel.isKeyguardOccluded(),
331                      this::setKeyguardOccluded
332              );
333          }
334          if (ComposeBouncerFlags.INSTANCE.isComposeBouncerOrSceneContainerEnabled()) {
335              collectFlow(mWindowRootView, mNotificationShadeWindowModel.isBouncerShowing(),
336                      this::setBouncerShowing);
337              collectFlow(mWindowRootView, mNotificationShadeWindowModel.getDoesBouncerRequireIme(),
338                      this::setKeyguardNeedsInput);
339          }
340      }

添加通知栏窗口

NotificationShadeWindowControllerImpl 复制代码
//https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
 public void attach() {
          // Now that the notification shade encompasses the sliding panel and its
          // translucent backdrop, the entire thing is made TRANSLUCENT and is
          // hardware-accelerated.
          // mLP is assigned here (instead of the constructor) as its null value is also used to check
          // if the shade window has been attached.
          mLp = mShadeWindowLayoutParams;
          mWindowManager.addView(mWindowRootView, mLp);
  
          // 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.
          if (mWindowRootView.getWindowInsetsController() != null) {
              mWindowRootView.getWindowInsetsController().setSystemBarsBehavior(
                      BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
          }
  
          mLpChanged.copyFrom(mLp);
          onThemeChanged();
  
          // Make the state consistent with KeyguardViewMediator#setupLocked during initialization.
          if (mKeyguardViewMediator.isShowingAndNotOccluded()) {
              setKeyguardShowing(true);
          }
      }

添加状态栏窗口

StatusBarWindowControllerImpl 复制代码
//https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java
  public void attach() {
          if (StatusBarConnectedDisplays.isEnabled()) {
              mStatusBarWindowView.setStatusBarConfigurationController(
                      mStatusBarConfigurationController);
          }
          // Now that the status bar window encompasses the sliding panel and its
          // translucent backdrop, the entire thing is made TRANSLUCENT and is
          // hardware-accelerated.
          Trace.beginSection("StatusBarWindowController.getBarLayoutParams");
          mLp = getBarLayoutParams(mContext.getDisplay().getRotation());
          Trace.endSection();
  
          try {
              mWindowManager.addView(mStatusBarWindowView, mLp);
          } catch (WindowManager.InvalidDisplayException e) {
              // Wrapping this in a try/catch to avoid crashes when a display is instantly removed
              // after being added, and initialization hasn't finished yet.
              Log.e(
                      TAG,
                      "Unable to add view to WindowManager. Display with id "
                              + mContext.getDisplayId()
                              + " doesn't exist anymore.",
                      e);
          }
          mLpChanged.copyFrom(mLp);
  
          mContentInsetsProvider.addCallback(this::calculateStatusBarLocationsForAllRotations);
          calculateStatusBarLocationsForAllRotations();
          mIsAttached = true;
          apply(mCurrentState);
   }
相关推荐
朱涛的自习室16 小时前
一个 7 x 24 小时为你打工的 AI,Munk AI 开始内测
android·前端·人工智能
李斯维17 小时前
腾讯 Mars XLog 日志框架的编译和修改
android
2501_9160088917 小时前
iOS IPA文件反编译与打包操作方法,拆包分析防护和加固打包
android·macos·ios·小程序·uni-app·cocoa·iphone
summerkissyou198717 小时前
Android16-性能-Perfetto的pbtxt 完整配置大全
android·性能
summerkissyou198718 小时前
Android-性能-Android Studio 2025 Profiler-教程
android·性能
小白说大模型20 小时前
KMP全栈开发:从Android到AI Agent的技术演进与实践
android·java·人工智能·windows·python
小小勇气大爆发20 小时前
Android17适配总结
android
开源推荐官21 小时前
getInvoice 是回填不是开票,Tigshop开源商城发票接口理一理
android·开源·php
醉城夜风~21 小时前
HTML表单域学习博客:表单标签、输入框、按钮详解
android·java·缓存