SystemUI启动的时候,读取要启动的核心组件(不再通过config.xml):
- SystemUIService调用SystemUIApplication的startSystemUserServicesIfNeeded()
- 通过 Dagger 组件 (
mSysUIComponent) 获取所有标注好的CoreStartable实现类。 - 通过 Dagger 的
@Binds注解自动注入到getStartables()集合中。
//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列表,依次调用每个CoreStartable的start()方法。 - 处理传入的
vendorComponent字符串,通过反射机制实例化并启动这个厂商自定义组件。
//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
启动状态栏,通知栏,导航栏
//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();
...
// 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,同时返回服务端保存的图标列表
//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:决定了哪些图标应在开机时加载到状态栏。它会根据系统状态(如蓝牙是否开启、是否有闹钟等)来显示和隐藏系统图标。CentralSurfacesImpl:SystemUI的主入口,负责初始化整体布局并实例。化PhoneStatusBarPolicy。StatusBarManagerService:系统服务,负责接收并管理来自各个应用的图标更新请求。IconManager:实际负责将StatusBarIconView添加到状态栏布局中。StatusBarIconView:负责单个图标的具体显示和更。StatusBarIconControllerImpl:作为中间层,将PhoneStatusBarPolicy的控制指令分发到具体的IconManager去执行。
//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);
}
状态栏图标列表配置在config.xml 中的 config_statusBarIcons 数组,StatusBarIconControllerImpl的构造函数中初始化StatusBarIconList的时候通过Dagger注入
//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));
}
创建状态栏,通知栏,导航栏
//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
//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
// 才走“老路”,手动调用 StatusBarInitializer 来初始化状态栏
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));
}
加载状态栏:
super_status_bar为状态栏根布局,在StatusBarWindowControllerImpl的构造函数中通过StatusBarWindowViewInflater来加载。StatusBarWindowViewInflater的实现类是StatusBarWindowViewInflaterImpl。mStatusBarWindowControllerStore( StatusBarWindowControllerStore)在CentralSurfacesImpl的构造函数中初始化,实际就是构造一个StatusBarWindowControllerImpl。CollapsedStatusBarFragment负责展示,管理状态栏的布局和具体UI元素, 在CentralSurfacesImpl的构造函数中初始化StatusBarInitializer,通过StatusBarInitializer被动态地替换到super_status_bar.xml的ID为status_bar_container容器中。super_status_bar.xml是状态栏的根布局。
//https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java
public StatusBarWindowControllerImpl(
100 @Assisted Context context,
101 @InternalWindowViewInflater StatusBarWindowViewInflater statusBarWindowViewInflater,
102 @Assisted WindowManager windowManager,
103 @Assisted StatusBarConfigurationController statusBarConfigurationController,
104 IWindowManager iWindowManager,
105 @Assisted StatusBarContentInsetsProvider contentInsetsProvider,
106 FragmentService fragmentService,
107 Optional<UnfoldTransitionProgressProvider> unfoldTransitionProgressProvider,
108 @Main Executor mainExecutor) {
109 mContext = context;
110 mWindowManager = windowManager;
111 mStatusBarConfigurationController = statusBarConfigurationController;
112 mIWindowManager = iWindowManager;
113 mContentInsetsProvider = contentInsetsProvider;
114 mMainExecutor = mainExecutor;
115 mStatusBarWindowView = statusBarWindowViewInflater.inflate(context);
116 mFragmentService = fragmentService;
117 mLaunchAnimationContainer = mStatusBarWindowView.findViewById(
118 R.id.status_bar_launch_animation_container);
119 mLpChanged = new WindowManager.LayoutParams();
120
121 if (mBarHeight < 0) {
122 mBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
123 }
124 unfoldTransitionProgressProvider.ifPresent(
125 unfoldProgressProvider -> unfoldProgressProvider.addCallback(
126 new JankMonitorTransitionProgressListener(
127 /* attachedViewProvider=*/ () -> mStatusBarWindowView)));
128 }
//https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowViewInflater.kt
interface StatusBarWindowViewInflater {
fun inflate(context: Context): StatusBarWindowView
}
class StatusBarWindowViewInflaterImpl @Inject constructor() : StatusBarWindowViewInflater {
override fun inflate(context: Context): StatusBarWindowView {
val layoutInflater = LayoutInflater.from(context)
return layoutInflater.inflate(R.layout.super_status_bar, /* root= */ null)
as StatusBarWindowView?
?: throw IllegalStateException(
"R.layout.super_status_bar could not be properly inflated"
)
}
}
//初始化CollapsedStatusBarFragment
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
override fun start() {
doStart()
}
override fun initializeStatusBar() {
StatusBarRootModernization.assertInLegacyMode()
doStart()
}
private fun doStart() {
if (StatusBarRootModernization.isEnabled) doComposeStart() else doLegacyStart()
}
/**
* Stand up the [PhoneStatusBarView] in a compose root. There will be no
* [CollapsedStatusBarFragment] in this mode
*/
private fun doComposeStart() {
initialized = true
val statusBarRoot =
statusBarRootFactory.create(statusBarWindowController.backgroundView as ViewGroup) { cv
->
val phoneStatusBarView = cv.findViewById<PhoneStatusBarView>(R.id.status_bar)
component =
componentFactory
.create(
phoneStatusBarView,
statusBarConfigurationController,
statusBarWindowController,
darkIconDispatcher,
)
.also { component ->
// CollapsedStatusBarFragment used to be responsible initializing
component.init()
statusBarViewUpdatedListener?.onStatusBarViewUpdated(
component.phoneStatusBarViewController,
component.phoneStatusBarTransitions,
)
if (StatusBarConnectedDisplays.isEnabled) {
statusBarModePerDisplayRepository.onStatusBarViewInitialized(
component
)
} else {
creationListeners.forEach { listener ->
listener.onStatusBarViewInitialized(component)
}
}
}
}
// Add the new compose view to the hierarchy because we don't use fragment transactions
// anymore
val windowBackgroundView = statusBarWindowController.backgroundView as ViewGroup
windowBackgroundView.addView(statusBarRoot)
}
private fun doLegacyStart() {
initialized = true
statusBarWindowController.fragmentHostManager
.addTagListener(
CollapsedStatusBarFragment.TAG,
object : FragmentHostManager.FragmentListener {
override fun onFragmentViewCreated(tag: String, fragment: Fragment) {
val statusBarFragment = fragment as CollapsedStatusBarFragment
if (statusBarFragment.homeStatusBarComponent == null) {
return
}
component = fragment.homeStatusBarComponent
statusBarViewUpdatedListener?.onStatusBarViewUpdated(
component!!.phoneStatusBarViewController,
component!!.phoneStatusBarTransitions,
)
creationListeners.forEach { listener ->
listener.onStatusBarViewInitialized(component!!)
}
}
override fun onFragmentViewDestroyed(tag: String?, fragment: Fragment?) {
// nop
}
},
)
.fragmentManager
.beginTransaction()
.replace(
R.id.status_bar_container,
collapsedStatusBarFragmentProvider.get(),
CollapsedStatusBarFragment.TAG,
)
.commit()
}
加载通知栏,初始化入口变得更隐蔽。super_notification_shade为通知栏根布局。NotificationShadeWindowControllerImpl构造函数创建windowRootViewComponent,CentralSurfacesImpl的构造函数又会创建NotificationShadeWindowControllerImpl。
https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
public NotificationShadeWindowControllerImpl(
@ShadeDisplayAware Context context,
WindowRootViewComponent.Factory windowRootViewComponentFactory,
@ShadeDisplayAware WindowManager windowManager,
IActivityManager activityManager,
DozeParameters dozeParameters,
StatusBarStateController statusBarStateController,
@ShadeDisplayAware ConfigurationController configurationController,
KeyguardViewMediator keyguardViewMediator,
KeyguardBypassController keyguardBypassController,
@Main Executor mainExecutor,
@Background Executor backgroundExecutor,
SysuiColorExtractor colorExtractor,
DumpManager dumpManager,
KeyguardStateController keyguardStateController,
AuthController authController,
Lazy<ShadeInteractor> shadeInteractorLazy,
ShadeWindowLogger logger,
Lazy<SelectedUserInteractor> userInteractor,
UserTracker userTracker,
NotificationShadeWindowModel notificationShadeWindowModel,
Lazy<CommunalInteractor> communalInteractor,
@ShadeDisplayAware LayoutParams shadeWindowLayoutParams)
//https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
fun providesWindowRootView(
@ShadeDisplayAware layoutInflater: LayoutInflater,
viewModelFactory: SceneContainerViewModel.Factory,
containerConfigProvider: Provider<SceneContainerConfig>,
scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>,
overlaysProvider: Provider<Set<@JvmSuppressWildcards Overlay>>,
layoutInsetController: NotificationInsetsController,
sceneDataSourceDelegator: Provider<SceneDataSourceDelegator>,
qsSceneAdapter: Provider<QSSceneAdapter>,
sceneJankMonitorFactory: SceneJankMonitor.Factory,
windowRootViewKeyEventHandler: WindowRootViewKeyEventHandler,
): WindowRootView {
return if (SceneContainerFlag.isEnabled) {
checkNoSceneDuplicates(scenesProvider.get())
val sceneWindowRootView =
layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView
sceneWindowRootView.init(
viewModelFactory = viewModelFactory,
containerConfig = containerConfigProvider.get(),
sharedNotificationContainer =
sceneWindowRootView.requireViewById(R.id.shared_notification_container),
scenes = scenesProvider.get(),
overlays = overlaysProvider.get(),
layoutInsetController = layoutInsetController,
sceneDataSourceDelegator = sceneDataSourceDelegator.get(),
qsSceneAdapter = qsSceneAdapter,
sceneJankMonitorFactory = sceneJankMonitorFactory,
windowRootViewKeyEventHandler = windowRootViewKeyEventHandler,
)
sceneWindowRootView
} else {
layoutInflater.inflate(R.layout.super_notification_shade, null)
}
as WindowRootView?
?: throw IllegalStateException("Window root view could not be properly inflated")
}
//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 }
创建导航栏
//https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
StatusBarConnectedDisplays.assertInLegacyMode();
//NavigationBarControllerImpl mNavigationBarController
mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
}
//https://xrefandroid.com/android-16.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
public void createNavigationBars(final boolean includeDefaultDisplay,
RegisterStatusBarResult result) {
// Don't need to create nav bar on the default display if we initialize TaskBar.
final boolean shouldCreateDefaultNavbar = includeDefaultDisplay
&& !initializeTaskbarIfNecessary();
Display[] displays = mDisplayTracker.getAllDisplays();
for (Display display : displays) {
if (shouldCreateDefaultNavbar
|| display.getDisplayId() != mDisplayTracker.getDefaultDisplayId()) {
createNavigationBar(display, null /* savedState */, result);
}
}
}
添加通知栏窗口
```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);
}
}
添加状态栏窗口
//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);
}