Android 12系统源码

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

前言

上一篇我们具体分析了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.Builder
                    statusBarNotificationActivityStarterBuilder,
            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 {
    @Override
    public 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;
        ...代码省略...
    }   

    @Override
    public 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();
     	...代码省略...
     }
}

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

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

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

@SysUISingleton
public class StatusBarWindowController {
    @Inject
    public 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的来源了因为需要知道其对应的布局文件。

3StatusBarWindowController最早是被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 {
    @Module
    companion object {
    	//提供一个单例的StatusBarWindowView对象实例
        @JvmStatic
        @Provides
        @SysUISingleton
        @InternalWindowView
        fun 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.StatusBarWindowView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:sysui="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <FrameLayout
        android:id="@+id/status_bar_launch_animation_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <FrameLayout
        android:id="@+id/status_bar_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/system_bar_background" />
</com.android.systemui.statusbar.window.StatusBarWindowView>

根控件是StatusBarWindowView正是我们之前多次提到的状态栏窗口对象其内部有两个FrameLayoutid为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.Factory
    interface 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 {
    @Override
    public 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.PhoneStatusBarView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
    android:layout_width="match_parent"
    android:layout_height="@dimen/status_bar_height"
    android:id="@+id/status_bar"
    android:orientation="vertical"
    android:focusable="false"
    android:descendantFocusability="afterDescendants"
    android:accessibilityPaneTitle="@string/status_bar"
    >

    <!--是否有新通知的标志-->
    <ImageView
        android:id="@+id/notification_lights_out"
        android:layout_width="@dimen/status_bar_icon_size"
        android:layout_height="match_parent"
        android:paddingStart="@dimen/status_bar_padding_start"
        android:paddingBottom="2dip"
        android:src="@drawable/ic_sysbar_lights_out_dot_small"
        android:scaleType="center"
        android:visibility="gone"
        />

    <!--状态栏视图-->
    <LinearLayout android:id="@+id/status_bar_contents"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingStart="@dimen/status_bar_padding_start"
        android:paddingEnd="@dimen/status_bar_padding_end"
        android:paddingTop="@dimen/status_bar_padding_top"
        android:orientation="horizontal"
        >
        <FrameLayout
            android:layout_height="match_parent"
            android:layout_width="0dp"
            android:layout_weight="1">

            <include layout="@layout/heads_up_status_bar_layout" />

            <!-- The alpha of the left side is controlled by PhoneStatusBarTransitions, and the
             individual views are controlled by StatusBarManager disable flags DISABLE_CLOCK and
             DISABLE_NOTIFICATION_ICONS, respectively -->
            <LinearLayout
                android:id="@+id/status_bar_left_side"
                android:layout_height="match_parent"
                android:layout_width="match_parent"
                android:clipChildren="false"
            >
                <!--延时启动设备用户名称-->
                <ViewStub
                    android:id="@+id/operator_name"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout="@layout/operator_name" />
                <!--时钟-->
                <com.android.systemui.statusbar.policy.Clock
                    android:id="@+id/clock"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:textAppearance="@style/TextAppearance.StatusBar.Clock"
                    android:singleLine="true"
                    android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
                    android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
                    android:gravity="center_vertical|start"
                />
                <!--正在进行的电话-->
                <include layout="@layout/ongoing_call_chip" />
                <!--下拉通知页面图标区域-->
                <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
                    android:id="@+id/notification_icon_area"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:orientation="horizontal"
                    android:clipChildren="false"/>

            </LinearLayout>
        </FrameLayout>

        <!-- Space should cover the notch (if it exists) and let other views lay out around it -->
        <android.widget.Space
            android:id="@+id/cutout_space_view"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:gravity="center_horizontal|center_vertical"
        />

        <!--下拉通知页面的中心图标区域-->
        <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
            android:id="@+id/centered_icon_area"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            android:clipChildren="false"
            android:gravity="center_horizontal|center_vertical"/>

        <!--状态栏系统图标区域-->
        <com.android.keyguard.AlphaOptimizedLinearLayout
            android:id="@+id/system_icon_area"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:gravity="center_vertical|end"
            >
            <!--系统图标-->
            <include layout="@layout/system_icons" />
        </com.android.keyguard.AlphaOptimizedLinearLayout>
    </LinearLayout>

    <!--延迟加载 紧急电话文字-->
    <ViewStub
        android:id="@+id/emergency_cryptkeeper_text"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout="@layout/emergency_cryptkeeper_text"
    />

</com.android.systemui.statusbar.phone.PhoneStatusBarView>

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;
    @Inject
    public 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中。

六、总结

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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: android