前言

上一篇我们具体分析了SystemUI的启动流程,在SystemServer的startOtherServices方法中,会启动SystemUIService服务,SystemUIService服务的onCreate方法会继续调用SystemUIApplication的startServicesIfNeeded方法,在该方法中会获取SystemUI组件各个类的具体路径,并通过和dagger2相关的ComponentHelper关键接口,获取SystemUI组件对应的实例对象,然后依次调用每个组件的start() 方法启动相关类的服务,启动完成后,又会再次调用该组件的onBootCompleted( ) 方法。

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

    private void startServicesIfNeeded(String metricsPrefix, String[] services) {if (mServicesStarted) {//如果服务已经启动直接返回return;}mServices = new SystemUI[services.length];...代码省略...     final int N = services.length;for (int i = 0; i < N; i++) {String clsName = services[i];//具体SystemUI组件类的完整路径long ti = System.currentTimeMillis();try {SystemUI obj = mComponentHelper.resolveSystemUI(clsName);//ComponentHelper的resolveSystemUI方法可以通过类名拿到具体的SystemUI实例对象if (obj == null) {//如果通过ComponentHelper的resolveSystemUI没有成功获取到实例对象,则通过反射创建,代码基本上不会走这里。Constructor constructor = Class.forName(clsName).getConstructor(Context.class);obj = (SystemUI) constructor.newInstance(this);//通过反射创建实例对象}mServices[i] = obj;//将获取的obj实例对象赋值到数组中。} catch (ClassNotFoundException| NoSuchMethodException| IllegalAccessException| InstantiationException| InvocationTargetException ex) {throw new RuntimeException(ex);}...代码省略...     mServices[i].start();...代码省略...     if (mBootCompleteCache.isBootComplete()) {mServices[i].onBootCompleted();}...代码省略...     }...代码省略...   mServicesStarted = true;//服务已经被启动}

frameworks/base/packages/SystemUI/res/values/config.xml

    <string-array name="config_systemUIServiceComponents" translatable="false"><item>com.android.systemui.util.NotificationChannels</item><!--通知--><item>com.android.systemui.keyguard.KeyguardViewMediator</item><!--键盘锁状态--><item>com.android.systemui.recents.Recents</item><!--任务列表--><item>com.android.systemui.volume.VolumeUI</item><!--监听音量,并决定是否显示音量的对话框--><item>com.android.systemui.statusbar.phone.StatusBar</item><!--状态栏--><item>com.android.systemui.usb.StorageNotification</item><!--监听 USB 连接状态并发送通知进行提示--><item>com.android.systemui.power.PowerUI</item><!--监听电量状态并在低电量时发送通知--><item>com.android.systemui.media.RingtonePlayer</item><!--用于播放铃声--><item>com.android.systemui.keyboard.KeyboardUI</item><!--键盘锁 UI--><item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item><!--快捷分发器--><item>@string/config_systemUIVendorServiceComponent</item><!--这里可以定义厂商定制的组件--><item>com.android.systemui.util.leak.GarbageMonitor$Service</item><!--用于监控内存泄漏的服务--><item>com.android.systemui.LatencyTester</item><!--仅在 debug 环境执行,用于监听系统测试延迟的模拟动作--><item>com.android.systemui.globalactions.GlobalActionsComponent</item><!--用于显示全局对话框(例如长按电源按键)--><item>com.android.systemui.ScreenDecorations</item><!--处理页面中的显示的形状(如圆角)--><item>com.android.systemui.biometrics.AuthController</item><!--身份验证--><item>com.android.systemui.SliceBroadcastRelayHandler</item><!--允许打开设置App--><item>com.android.systemui.statusbar.notification.InstantAppNotifier</item><!--时应用程序通知--><item>com.android.systemui.theme.ThemeOverlayController</item><!--主题--><item>com.android.systemui.accessibility.WindowMagnification</item><!--放大器--><item>com.android.systemui.accessibility.SystemActions</item><item>com.android.systemui.toast.ToastUI</item><item>com.android.systemui.wmshell.WMShell</item></string-array>

本篇文章我们主要来分析一下com.android.systemui.statusbar.phone.StatusBar所对应的状态栏类的创建过程。

一、StatusBar的构造方法

1、通过前面的分析我们知道,SystemUI的所有组件实例都是通过和dagger2相关的ComponentHelper类得到的,该类中的的SystemUI组件实例最初是通过dagger2的依赖注入得到的,而dagger2在实例化SystemUI组件的时候,会调用对应组件的构造方法,StatusBar的构造方法如下所示:

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

public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {public StatusBar(Context context,NotificationsController notificationsController,FragmentService fragmentService,LightBarController lightBarController,AutoHideController autoHideController,StatusBarWindowController statusBarWindowController,//状态栏控制器KeyguardUpdateMonitor keyguardUpdateMonitor,StatusBarSignalPolicy statusBarSignalPolicy,PulseExpansionHandler pulseExpansionHandler,NotificationWakeUpCoordinator notificationWakeUpCoordinator,KeyguardBypassController keyguardBypassController,KeyguardStateController keyguardStateController,HeadsUpManagerPhone headsUpManagerPhone,DynamicPrivacyController dynamicPrivacyController,BypassHeadsUpNotifier bypassHeadsUpNotifier,FalsingManager falsingManager,FalsingCollector falsingCollector,BroadcastDispatcher broadcastDispatcher,NotifShadeEventSource notifShadeEventSource,NotificationEntryManager notificationEntryManager,NotificationGutsManager notificationGutsManager,NotificationLogger notificationLogger,NotificationInterruptStateProvider notificationInterruptStateProvider,NotificationViewHierarchyManager notificationViewHierarchyManager,PanelExpansionStateManager panelExpansionStateManager,KeyguardViewMediator keyguardViewMediator,DisplayMetrics displayMetrics,MetricsLogger metricsLogger,@UiBackground Executor uiBgExecutor,NotificationMediaManager notificationMediaManager,NotificationLockscreenUserManager lockScreenUserManager,NotificationRemoteInputManager remoteInputManager,UserSwitcherController userSwitcherController,NetworkController networkController,BatteryController batteryController,SysuiColorExtractor colorExtractor,ScreenLifecycle screenLifecycle,WakefulnessLifecycle wakefulnessLifecycle,SysuiStatusBarStateController statusBarStateController,Optional<BubblesManager> bubblesManagerOptional,Optional<Bubbles> bubblesOptional,VisualStabilityManager visualStabilityManager,DeviceProvisionedController deviceProvisionedController,NavigationBarController navigationBarController,AccessibilityFloatingMenuController accessibilityFloatingMenuController,Lazy<AssistManager> assistManagerLazy,ConfigurationController configurationController,NotificationShadeWindowController notificationShadeWindowController,DozeParameters dozeParameters,ScrimController scrimController,Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,LockscreenGestureLogger lockscreenGestureLogger,Lazy<BiometricUnlockController> biometricUnlockControllerLazy,DozeServiceHost dozeServiceHost,PowerManager powerManager,ScreenPinningRequest screenPinningRequest,DozeScrimController dozeScrimController,VolumeComponent volumeComponent,CommandQueue commandQueue,CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,StatusBarComponent.Factory statusBarComponentFactory,//状态栏组件工厂PluginManager pluginManager,Optional<LegacySplitScreen> splitScreenOptional,LightsOutNotifController lightsOutNotifController,StatusBarNotificationActivityStarter.BuilderstatusBarNotificationActivityStarterBuilder,ShadeController shadeController,StatusBarKeyguardViewManager statusBarKeyguardViewManager,ViewMediatorCallback viewMediatorCallback,InitController initController,@Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,PluginDependencyProvider pluginDependencyProvider,KeyguardDismissUtil keyguardDismissUtil,ExtensionController extensionController,UserInfoControllerImpl userInfoControllerImpl,OperatorNameViewController.Factory operatorNameViewControllerFactory,PhoneStatusBarPolicy phoneStatusBarPolicy,KeyguardIndicationController keyguardIndicationController,DemoModeController demoModeController,Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,StatusBarTouchableRegionManager statusBarTouchableRegionManager,NotificationIconAreaController notificationIconAreaController,BrightnessSliderController.Factory brightnessSliderFactory,WallpaperController wallpaperController,OngoingCallController ongoingCallController,SystemStatusAnimationScheduler animationScheduler,StatusBarLocationPublisher locationPublisher,StatusBarIconController statusBarIconController,StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,LockscreenShadeTransitionController lockscreenShadeTransitionController,FeatureFlags featureFlags,KeyguardUnlockAnimationController keyguardUnlockAnimationController,@Main Handler mainHandler,@Main DelayableExecutor delayableExecutor,@Main MessageRouter messageRouter,WallpaperManager wallpaperManager,UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,Optional<StartingSurface> startingSurfaceOptional,TunerService tunerService,DumpManager dumpManager,ActivityLaunchAnimator activityLaunchAnimator) {super(context);mNotificationsController = notificationsController;mFragmentService = fragmentService;mLightBarController = lightBarController;mAutoHideController = autoHideController;mStatusBarWindowController = statusBarWindowController;mKeyguardUpdateMonitor = keyguardUpdateMonitor;mPulseExpansionHandler = pulseExpansionHandler;mWakeUpCoordinator = notificationWakeUpCoordinator;mKeyguardBypassController = keyguardBypassController;mKeyguardStateController = keyguardStateController;mHeadsUpManager = headsUpManagerPhone;mOperatorNameViewControllerFactory = operatorNameViewControllerFactory;mKeyguardIndicationController = keyguardIndicationController;mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;mDynamicPrivacyController = dynamicPrivacyController;mBypassHeadsUpNotifier = bypassHeadsUpNotifier;mFalsingCollector = falsingCollector;mFalsingManager = falsingManager;mBroadcastDispatcher = broadcastDispatcher;mNotifShadeEventSource = notifShadeEventSource;mEntryManager = notificationEntryManager;mGutsManager = notificationGutsManager;mNotificationLogger = notificationLogger;mNotificationInterruptStateProvider = notificationInterruptStateProvider;mViewHierarchyManager = notificationViewHierarchyManager;mPanelExpansionStateManager = panelExpansionStateManager;mKeyguardViewMediator = keyguardViewMediator;mDisplayMetrics = displayMetrics;mMetricsLogger = metricsLogger;mUiBgExecutor = uiBgExecutor;mMediaManager = notificationMediaManager;mLockscreenUserManager = lockScreenUserManager;mRemoteInputManager = remoteInputManager;mUserSwitcherController = userSwitcherController;mNetworkController = networkController;mBatteryController = batteryController;mColorExtractor = colorExtractor;mScreenLifecycle = screenLifecycle;mWakefulnessLifecycle = wakefulnessLifecycle;mStatusBarStateController = statusBarStateController;mBubblesManagerOptional = bubblesManagerOptional;mBubblesOptional = bubblesOptional;mVisualStabilityManager = visualStabilityManager;mDeviceProvisionedController = deviceProvisionedController;mNavigationBarController = navigationBarController;mAccessibilityFloatingMenuController = accessibilityFloatingMenuController;mAssistManagerLazy = assistManagerLazy;mConfigurationController = configurationController;mNotificationShadeWindowController = notificationShadeWindowController;mDozeServiceHost = dozeServiceHost;mPowerManager = powerManager;mDozeParameters = dozeParameters;mScrimController = scrimController;mLockscreenWallpaperLazy = lockscreenWallpaperLazy;mLockscreenGestureLogger = lockscreenGestureLogger;mScreenPinningRequest = screenPinningRequest;mDozeScrimController = dozeScrimController;mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy;mVolumeComponent = volumeComponent;mCommandQueue = commandQueue;mCollapsedStatusBarFragmentLogger = collapsedStatusBarFragmentLogger;mStatusBarComponentFactory = statusBarComponentFactory;mPluginManager = pluginManager;mSplitScreenOptional = splitScreenOptional;mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder;mShadeController = shadeController;mLightsOutNotifController =  lightsOutNotifController;mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;mKeyguardViewMediatorCallback = viewMediatorCallback;mInitController = initController;mPluginDependencyProvider = pluginDependencyProvider;mKeyguardDismissUtil = keyguardDismissUtil;mExtensionController = extensionController;mUserInfoControllerImpl = userInfoControllerImpl;mIconPolicy = phoneStatusBarPolicy;mDemoModeController = demoModeController;mNotificationIconAreaController = notificationIconAreaController;mBrightnessSliderFactory = brightnessSliderFactory;mWallpaperController = wallpaperController;mOngoingCallController = ongoingCallController;mAnimationScheduler = animationScheduler;mStatusBarSignalPolicy = statusBarSignalPolicy;mStatusBarLocationPublisher = locationPublisher;mStatusBarIconController = statusBarIconController;mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;mFeatureFlags = featureFlags;mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;mMainHandler = mainHandler;mMainExecutor = delayableExecutor;mMessageRouter = messageRouter;mWallpaperManager = wallpaperManager;mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;mTunerService = tunerService;mLockscreenShadeTransitionController = lockscreenShadeTransitionController;mStartingSurfaceOptional = startingSurfaceOptional;lockscreenShadeTransitionController.setStatusbar(this);mPanelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);mBubbleExpandListener =(isExpanding, key) -> mContext.getMainExecutor().execute(() -> {mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged");updateScrimController();});mActivityIntentHelper = new ActivityIntentHelper(mContext);mActivityLaunchAnimator = activityLaunchAnimator;// The status bar background may need updating when the ongoing call status changes.mOngoingCallController.addCallback((animate) -> maybeUpdateBarMode());// TODO(b/190746471): Find a better home for this.DateTimeView.setReceiverHandler(timeTickHandler);mMessageRouter.subscribeTo(KeyboardShortcutsMessage.class,data -> toggleKeyboardShortcuts(data.mDeviceId));mMessageRouter.subscribeTo(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU,id -> dismissKeyboardShortcuts());mMessageRouter.subscribeTo(AnimateExpandSettingsPanelMessage.class,data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel));mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT,id -> onLaunchTransitionTimeout());}}

StatusBar的构造方法乍一看简直恐怖如斯,因为它的参数居然足足有100多个,这种代码要是放在以前,肯定妥妥的被骂翻!构造方法参数如此之多别人要如何创建对象实例?幸好现在有了Dagger2框架的加持,该框架会自动帮我们创建对象实例并传入StatusBar需要的所有参数,我们直接在StatusBar中用就是了,所以构造方法就算有再多参数也不是什么大问题了。

二、从StatusBar的start方法到状态栏视图窗口StatusBarWindowView的创建

1、结合前面SystemUIApplication的startServicesIfNeeded方法我们知道,在获得每个SystemUI组件对象之后,都会调用该对象的start方法,作为SystemUI组件之一的StatusBar自然也不例外:

public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {@Overridepublic void start() {...代码省略...createAndAddWindows(result);...代码省略...}
}

start方法会调用一个叫createAndAddWindows的关键方法,系统状态栏视图的创建和添加工作就是在该方法中完成的。

2、和createAndAddWindows方法相关的代码如下所示:

public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {private final StatusBarWindowController mStatusBarWindowController;//状态栏窗口控制器private final StatusBarComponent.Factory mStatusBarComponentFactory;//Dagger2状态栏组件工厂private StatusBarComponent mStatusBarComponent;//Dagger2状态栏子组件protected PhoneStatusBarView mStatusBarView;//状态栏视图private PhoneStatusBarViewController mPhoneStatusBarViewController;//状态栏视图控制器public StatusBar(...代码省略...StatusBarWindowController statusBarWindowController,//状态栏控制器StatusBarComponent.Factory statusBarComponentFactory,//状态栏Dagger2组件工厂...代码省略...){...代码省略...//为状态栏控制器mStatusBarWindowController赋值mStatusBarWindowController = statusBarWindowController;//为状态栏Dagger2组件工厂mStatusBarComponentFactory赋值mStatusBarComponentFactory = statusBarComponentFactory;...代码省略...}   @Overridepublic void start() {...代码省略...createAndAddWindows(result);...代码省略...}public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {makeStatusBarView(result);...代码省略...mStatusBarWindowController.attach();}protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {...代码省略...inflateStatusBarWindow();...代码省略...mStatusBarWindowController.getFragmentHostManager().addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {代码省略}).getFragmentManager().beginTransaction().replace(R.id.status_bar_container,mStatusBarComponent.createCollapsedStatusBarFragment(),CollapsedStatusBarFragment.TAG).commit();...代码省略...}private void inflateStatusBarWindow() {mStatusBarComponent = mStatusBarComponentFactory.create();...代码省略...}
}

1)StatusBar的构造方法会为状态栏窗口控制器mStatusBarWindowController和Dagger2状态栏组件工厂mStatusBarComponentFactory对象赋值。createAndAddWindows首先调用了makeStatusBarView方法来构建视图,makeStatusBarView方法又会调用inflateStatusBarWindow方法,inflateStatusBarWindow方法内部又调用mStatusBarComponentFactory的create方法为Dagger2状态栏组件mStatusBarComponent赋值。等inflateStatusBarWindow方法执行完毕,makeStatusBarView方法会调用mStatusBarWindowController的getFragmentHostManager来获取FragmentHostManager对象实例。

2)StatusBarWindowController和getFragmentHostManager方法相关的代码如下所示:

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

@SysUISingleton
public class StatusBarWindowController {@Injectpublic StatusBarWindowController(Context context,@StatusBarWindowModule.InternalWindowView StatusBarWindowView statusBarWindowView,WindowManager windowManager,IWindowManager iWindowManager,StatusBarContentInsetsProvider contentInsetsProvider,@Main Resources resources) {...代码省略...mStatusBarWindowView = statusBarWindowView;...代码省略...}public FragmentHostManager getFragmentHostManager() {return FragmentHostManager.get(mStatusBarWindowView);}
}

getFragmentHostManager内部会将mStatusBarWindowView作为唯一参数,继续调用FragmentHostManager的get方法。

frameworks/base/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java

public class FragmentHostManager {public static FragmentHostManager get(View view) {try {return Dependency.get(FragmentService.class).getFragmentHostManager(view);} catch (ClassCastException e) {// TODO: Some auto handling here?throw e;}}
}

FragmentHostManager的get方法继续调用FragmentService的getFragmentHostManager方法。

public class FragmentService implements Dumpable {public FragmentHostManager getFragmentHostManager(View view) {View root = view.getRootView();FragmentHostState state = mHosts.get(root);if (state == null) {//创建FragmentHostState对象实例state = new FragmentHostState(root);mHosts.put(root, state);}//调用FragmentHostState的getFragmentHostManager方法return state.getFragmentHostManager();} private class FragmentHostState {private final View mView;private FragmentHostManager mFragmentHostManager;public FragmentHostState(View view) {mView = view;//创建FragmentHostManager对象实例mFragmentHostManager = new FragmentHostManager(FragmentService.this, mView);}public FragmentHostManager getFragmentHostManager() {return mFragmentHostManager;}}
}

FragmentService的getFragmentHostManager会创建FragmentHostState对象实例,然后调用该对象的getFragmentHostManager方法,该方法会返回mFragmentHostManager,而mFragmentHostManager最早是在FragmentHostState自己的构造方法中创建的,原来绕了一圈,最后得到的结果其实就是,StatusBarWindowController的getFragmentHostManager方法会将StatusBarWindowView作为构造方法参数创建FragmentHostManager实例对象。

public class FragmentHostManager {private final View mRootView;FragmentHostManager(FragmentService manager, View rootView) {...代码省略...//将StatusBarWindowView赋值给mRootView mRootView = rootView;...代码省略...}

由于后续会用到mRootView,这里我们就有必要看一下StatusBarWindowView的来源了,因为需要知道其对应的布局文件。

3)StatusBarWindowController最早是被dagger2依赖注入到StatusBar中的,作为构造方法参数的StatusBarWindowView,也是被Dagger2依赖注入到StatusBarWindowController中的。Dagger2获取StatusBarWindowView对象实例的关键代码位于StatusBarWindowModule的providesStatusBarWindowView方法中:

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt

@Module
abstract class StatusBarWindowModule {@Modulecompanion object {//提供一个单例的StatusBarWindowView对象实例@JvmStatic@Provides@SysUISingleton@InternalWindowViewfun providesStatusBarWindowView(layoutInflater: LayoutInflater): StatusBarWindowView {return layoutInflater.inflate(R.layout.super_status_bar,/* root= */null) as StatusBarWindowView??: throw IllegalStateException("R.layout.super_status_bar could not be properly inflated")}}}

providesStatusBarWindowView直接将super_status_bar.xml布局文件转化为View对象,然后再将View转化为StatusBarWindowView进行返回,其中的super_status_bar.xml布局文件内容如下所示:

frameworks/base/packages/SystemUI/res/layout/super_status_bar.xml

<com.android.systemui.statusbar.window.StatusBarWindowViewxmlns: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"><FrameLayoutandroid:id="@+id/status_bar_launch_animation_container"android:layout_width="match_parent"android:layout_height="match_parent" /><FrameLayoutandroid: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.window.StatusBarWindowView>

根控件是StatusBarWindowView,正是我们之前多次提到的状态栏窗口对象,其内部有两个FrameLayout,id为status_bar_launch_animation_container的FrameLayout主要是负责状态栏打开其他Activity时候的切换动画,id为status_bar_container的FrameLayout则是承载状态栏视图内容的容器。

三、创建状态栏视图CollapsedStatusBarFragment

1、继续来看在StatusBar的makeStatusBarView方法。

   protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {...代码省略...mStatusBarWindowController.getFragmentHostManager().addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {代码省略}).getFragmentManager().beginTransaction().replace(R.id.status_bar_container,mStatusBarComponent.createCollapsedStatusBarFragment(),CollapsedStatusBarFragment.TAG).commit();...代码省略...}

在调用StatusBarWindowController的getFragmentHostManager获得FragmentHostManager实例对象之后,会继续调用addTagListener方法设置监听对象,然后获取FragmentManager并开启会话,再调用mStatusBarComponent的createCollapsedStatusBarFragment方法创建状态栏视图的CollapsedStatusBarFragment,将其对应的视图设置到id为status_bar_container的控件上。

2、StatusBarComponent和创建CollapsedStatusBarFragment对象实例有关的代码如下所示:

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java

@Subcomponent(modules = {StatusBarViewModule.class})
@StatusBarComponent.StatusBarScope
public interface StatusBarComponent {/*** Builder for {@link StatusBarComponent}.*/@Subcomponent.Factoryinterface Factory {StatusBarComponent create();}/*** Scope annotation for singleton items within the StatusBarComponent.*/@Documented@Retention(RUNTIME)@Scope@interface StatusBarScope {}/*** 每次被调用的时候会创建一个新的CollapsedStatusBarFragment实例对象*/CollapsedStatusBarFragment createCollapsedStatusBarFragment();
}

对java来说StatusBarComponent是一个接口,其内部的Factory对应了我们前面提到的状态栏组件工厂mStatusBarComponentFactory;而对于dagger2来说,StatusBarComponent是一个子连接器,且存在一个模块StatusBarViewModule。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java

@Module(subcomponents = StatusBarFragmentComponent.class)
public abstract class StatusBarViewModule {public static CollapsedStatusBarFragment createCollapsedStatusBarFragment(StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,OngoingCallController ongoingCallController,SystemStatusAnimationScheduler animationScheduler,StatusBarLocationPublisher locationPublisher,NotificationIconAreaController notificationIconAreaController,PanelExpansionStateManager panelExpansionStateManager,FeatureFlags featureFlags,StatusBarIconController statusBarIconController,StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,KeyguardStateController keyguardStateController,NotificationPanelViewController notificationPanelViewController,NetworkController networkController,StatusBarStateController statusBarStateController,CommandQueue commandQueue,CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,OperatorNameViewController.Factory operatorNameViewControllerFactory,SecureSettings secureSettings,@Main Executor mainExecutor) {return new CollapsedStatusBarFragment(statusBarFragmentComponentFactory,ongoingCallController,animationScheduler,locationPublisher,notificationIconAreaController,panelExpansionStateManager,featureFlags,statusBarIconController,statusBarHideIconsForBouncerManager,keyguardStateController,notificationPanelViewController,networkController,statusBarStateController,commandQueue,collapsedStatusBarFragmentLogger,operatorNameViewControllerFactory,secureSettings,mainExecutor);}
}

在StatusBarViewModule的createCollapsedStatusBarFragment方法内部创建了CollapsedStatusBarFragment对象实例,StatusBarComponent的createCollapsedStatusBarFragment最终触发的其实就是这个方法。

3、前面提到FragmentHostManager有调用addTagListener方法为设置监听对象,该监听对象的回调方法会在CollapsedStatusBarFragment的onViewCreated方法执行之后被调用。

   protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {...代码省略...mStatusBarWindowController.getFragmentHostManager().addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {StatusBarFragmentComponent statusBarFragmentComponent =((CollapsedStatusBarFragment) fragment).getStatusBarFragmentComponent();if (statusBarFragmentComponent == null) {throw new IllegalStateException("CollapsedStatusBarFragment should have a valid component");}//状态栏视图mStatusBarView = statusBarFragmentComponent.getPhoneStatusBarView();//状态栏视图控制器mPhoneStatusBarViewController =statusBarFragmentComponent.getPhoneStatusBarViewController();mNotificationPanelViewController.updatePanelExpansionAndVisibility();setBouncerShowingForStatusBarComponents(mBouncerShowing);mLightsOutNotifController.setLightsOutNotifView(mStatusBarView.findViewById(R.id.notification_lights_out));//为通知栏遮罩窗口控制器设置状态栏mNotificationShadeWindowViewController.setStatusBarView(mStatusBarView);checkBarModes();}).getFragmentManager().beginTransaction().replace(R.id.status_bar_container,mStatusBarComponent.createCollapsedStatusBarFragment(),CollapsedStatusBarFragment.TAG).commit();...代码省略...}

回调方法中首先将状态栏视图保存到mStatusBarView中,状态栏视图控制器保存到mPhoneStatusBarViewController 中,然后让状态栏视图和通知栏相关的类进行了一定的关联。

四、状态栏视图结构分析

1、CollapsedStatusBarFragment的代码很多,我们这里只讲一下它初始化布局文件的代码。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java

public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks,StatusBarStateController.StateListener,SystemStatusAnimationCallback {@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.status_bar, container, false);}
}

可以看到状态栏视图所对应的布局文件为status_bar.xml,该布局文件对应了系统状态栏所的视图内容。

frameworks/base/packages/SystemUI/res/layout/status_bar.xml

<com.android.systemui.statusbar.phone.PhoneStatusBarViewxmlns: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"><!--是否有新通知的标志--><ImageViewandroid: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"><FrameLayoutandroid: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 theindividual views are controlled by StatusBarManager disable flags DISABLE_CLOCK andDISABLE_NOTIFICATION_ICONS, respectively --><LinearLayoutandroid:id="@+id/status_bar_left_side"android:layout_height="match_parent"android:layout_width="match_parent"android:clipChildren="false"><!--延时启动,设备用户名称--><ViewStubandroid:id="@+id/operator_name"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout="@layout/operator_name" /><!--时钟--><com.android.systemui.statusbar.policy.Clockandroid: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.AlphaOptimizedFrameLayoutandroid: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.Spaceandroid:id="@+id/cutout_space_view"android:layout_width="0dp"android:layout_height="match_parent"android:gravity="center_horizontal|center_vertical"/><!--下拉通知页面的中心图标区域--><com.android.systemui.statusbar.AlphaOptimizedFrameLayoutandroid: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.AlphaOptimizedLinearLayoutandroid: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><!--延迟加载 紧急电话文字--><ViewStubandroid: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>

1)根控件是PhoneStatusBarView,其内部包含了状态栏的所有视图内容,大致结构如下所示。

2)下面是HierarchyViewer关于系统状态栏的一张视图结构分析图,基本可以对应上status_bar.xml布局文件。

五、将状态栏窗口添加到Window中

1、StatusBar的createAndAddWindows方法在调用makeStatusBarView方法构建好状态栏视图之后,便会调用StatusBarWindowController的attach方法。

public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {makeStatusBarView(result);...代码省略...mStatusBarWindowController.attach();}

2、StatusBarWindowController的attach方法方法如下所示:

@SysUISingleton
public class StatusBarWindowController {private final WindowManager mWindowManager;private WindowManager.LayoutParams mLp;@Injectpublic StatusBarWindowController(Context context,@StatusBarWindowModule.InternalWindowView StatusBarWindowView statusBarWindowView,WindowManager windowManager,IWindowManager iWindowManager,StatusBarContentInsetsProvider contentInsetsProvider,@Main Resources resources) {...代码省略...mWindowManager = windowManager;mStatusBarWindowView = statusBarWindowView;if (mBarHeight < 0) {mBarHeight = SystemBarUtils.getStatusBarHeight(mContext);}}public void attach() {//获取状态栏类型窗口所需要的布局参数mLp = getBarLayoutParams(mContext.getDisplay().getRotation());//调用WindowManager的addView方法将状态栏窗口添加到Window中。mWindowManager.addView(mStatusBarWindowView, mLp);...代码省略...}
}

3、attach首先调用getBarLayoutParams方法获取状态栏类型窗口所需要的布局参数,下面是获取状态栏类型窗口所需要的布局参数的相关代码

private WindowManager.LayoutParams getBarLayoutParams(int rotation) {WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation);lp.paramsForRotation = new WindowManager.LayoutParams[4];for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {lp.paramsForRotation[rot] = getBarLayoutParamsForRotation(rot);}return lp;}private WindowManager.LayoutParams getBarLayoutParamsForRotation(int rotation) {int height = mBarHeight;if (INSETS_LAYOUT_GENERALIZATION) {switch (rotation) {case ROTATION_UNDEFINED:case Surface.ROTATION_0:case Surface.ROTATION_180:height = SystemBarUtils.getStatusBarHeightForRotation(mContext, Surface.ROTATION_0);break;case Surface.ROTATION_90:height = SystemBarUtils.getStatusBarHeightForRotation(mContext, Surface.ROTATION_90);break;case Surface.ROTATION_270:height = SystemBarUtils.getStatusBarHeightForRotation(mContext, Surface.ROTATION_270);break;}}WindowManager.LayoutParams lp = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT,//填充设备整个宽度height,//根据当前屏幕旋转角度所得到的状态栏高度WindowManager.LayoutParams.TYPE_STATUS_BAR,//指定窗口类型为状态栏WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH| WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,PixelFormat.TRANSLUCENT);//窗口背景半透明lp.privateFlags |= PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;lp.token = new Binder();lp.gravity = Gravity.TOP;lp.setFitInsetsTypes(0 /* types */);lp.setTitle("StatusBar");lp.packageName = mContext.getPackageName();lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;return lp;}

4、在成功获取状态栏类型窗口所需要的布局参数后,便会调用WindowManager的addView方法将状态栏视图窗口添加到Window中。

六、总结

经过前面几步,我们初步分析完了状态栏视图的创建和添加流程,最后用一张图对前面的代码流程做一个回顾。

Android 12系统源码_SystemUI(二)系统状态栏StatusBar的创建流程相关推荐

  1. Android 12系统源码_SystemUI(一)SystemUI的启动流程

    前言 Android 的 SystemUI 其实就是 Android 的系统界面,它包括了界面上方的状态栏 status bar,下方的导航栏Navigation Bar,锁屏界面 Keyguard ...

  2. Android 9.0系统源码_SystemUI(一)SystemUI的启动流程

    一.SystemUI 介绍 1.初步认识SystemUI Android 的 SystemUI 其实就是 Android 的系统界面,它包括了界面上方的状态栏 status bar,下方的导航栏Nav ...

  3. 仿阿姨帮|58到家上门O2O系统源码( BAOCMS二次开发 )

    [实例简介] 仿阿姨帮|58到家上门O2O系统源码(BAOCMS二次开发 七牛云)是一款PHP MYSQL开发制作的在线上门O2O系统,,PC WAP 微信端等功能,在BAOCMS基础上二次开发的东西 ...

  4. java计算机毕业设计Web端校园报修系统源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计Web端校园报修系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计Web端校园报修系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈: 项目架构 ...

  5. java计算机毕业设计教师业绩考核和职称评审系统源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计教师业绩考核和职称评审系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计教师业绩考核和职称评审系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈 ...

  6. 计算机毕业设计Java考研部落系统(源码+mysql数据库+系统+lw文档)

    计算机毕业设计Java考研部落系统(源码+mysql数据库+系统+lw文档) 计算机毕业设计Java考研部落系统(源码+mysql数据库+系统+lw文档) 本源码技术栈: 项目架构:B/S架构 开发语 ...

  7. java计算机毕业设计汉字幼教系统源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计汉字幼教系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计汉字幼教系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开 ...

  8. java计算机毕业设计智能快递分拣系统源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计智能快递分拣系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计智能快递分拣系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈: 项目架构:B/S ...

  9. java计算机毕业设计教师招聘考试题库系统源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计教师招聘考试题库系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计教师招聘考试题库系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈: 项目架构 ...

  10. java计算机毕业设计驾考服务系统源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计驾考服务系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计驾考服务系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开 ...

最新文章

  1. 文件目录表(FDT)及其结构
  2. Centos7源码安装mysql及读写分离,互为主从
  3. Leetcode1690. 石子游戏 VII[C++题解]:带有博弈论的区间dp
  4. 20145315 《Java程序设计》实验五实验报告
  5. mybatis学习(29):适用于没有自增的数据库
  6. 长淋巴结注意事项问答
  7. 【2019.08.31】2019银川网络赛(2018银川现场赛)
  8. string字符串数字自增_常见的字符串操作
  9. SAP License:MR22借贷物料一步设置可以把差异带走
  10. 四年测试工程师经历,下一步转开发还是继续测试?
  11. 法拉利杀手Koenigsegg CCX
  12. C语言实现矩阵的乘法
  13. 共享服务器文件溢出,文件共享锁定数溢出
  14. Julia Pro国内下载地址
  15. 巧妙算法之位运算的应用
  16. 数据、源代码防泄密解决方案
  17. Flutter安装时你一定会碰到的问题
  18. ASEK711KLC-25AB-T霍尔效应线性电流传感器SOIC8
  19. 首个AI数字人唱作歌曲刷屏背后:百度APP数字人度晓晓用AI陪伴亿万用户
  20. SQL Server AlwaysOn读写分离配置

热门文章

  1. 2023届秋招总结_嵌入式软件开发
  2. matlab画雷克子波
  3. 安卓从服务器中下载pdf文件 然后调用第三方软件WPS Office打开
  4. 从零搭建Robot Framework+Jenkins持续集成环境
  5. autojs获取QQ群成员列表里的群员数据,免root脚本源码分享
  6. 怎么识别图片数据转到Excel?手机也能轻松做到
  7. 由还款计划表和还款历史表,生成历史每日逾期表_历史逾期情况回溯_Mysql存储过程实现
  8. oracle房贷还款计划,还款计划表数据查询
  9. 验证码加减乘PHP,ThinkPHP 3.2.3实现加减乘除图片验证码
  10. 招聘兼职招聘类APP开发分享