Android StatusBar 创建过程浅析

1,306 阅读3分钟

StatusBar

路径:frameworks/packages/SystemUI/statusbar/phone/statusbar

进来很清晰的可以看到 StatusBar 继承自 SystemUI ,所以我们直接去找对应的 start 方法。


    @Override
    public void start() {
        mGroupManager = Dependency.get(NotificationGroupManager.class);
        mGroupAlertTransferHelper = Dependency.get(NotificationGroupAlertTransferHelper.class);
        mVisualStabilityManager = Dependency.get(VisualStabilityManager.class);
        mNotificationLogger = Dependency.get(NotificationLogger.class);
        mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
        mNotificationListener =  Dependency.get(NotificationListener.class);
        mNotificationListener.registerAsSystemService();
        mNetworkController = Dependency.get(NetworkController.class);
        mUserSwitcherController = Dependency.get(UserSwitcherController.class);
        mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
        mScreenLifecycle.addObserver(mScreenObserver);
        mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
        mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
        mBatteryController = Dependency.get(BatteryController.class);
        mAssistManager = Dependency.get(AssistManager.class);
        mUiModeManager = mContext.getSystemService(UiModeManager.class);
        mLockscreenUserManager = Dependency.get(NotificationLockscreenUserManager.class);
        mGutsManager = Dependency.get(NotificationGutsManager.class);
        mMediaManager = Dependency.get(NotificationMediaManager.class);
        mEntryManager = Dependency.get(NotificationEntryManager.class);
        mNotificationInterruptionStateProvider =
                Dependency.get(NotificationInterruptionStateProvider.class);
        mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
        mForegroundServiceController = Dependency.get(ForegroundServiceController.class);
        mAppOpsController = Dependency.get(AppOpsController.class);
        mZenController = Dependency.get(ZenModeController.class);
        mKeyguardViewMediator = getComponent(KeyguardViewMediator.class);
        mColorExtractor = Dependency.get(SysuiColorExtractor.class);
        mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
        mNavigationBarController = Dependency.get(NavigationBarController.class);
        mBubbleController = Dependency.get(BubbleController.class);
        mBubbleController.setExpandListener(mBubbleExpandListener);
        mActivityIntentHelper = new ActivityIntentHelper(mContext);
        KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance();
        ···
        重点查看这个方法 创建状态栏和导航栏的方法
        createAndAddWindows(result);
        ···
    }

  //createAndAddWindows
  public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
        // 继续跟进这个方法
        makeStatusBarView(result);
        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
        mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
    }

    protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
        final Context context = mContext;
        //获取屏幕参数
        updateDisplaySize(); 
        updateResources();
        updateTheme();
        // 引入StatusBarWindow布局
        inflateStatusBarWindow(context);
        mStatusBarWindow.setService(this);
        // 设置触摸事件监听
        mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener());

        mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
        mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
        mZenController.addCallback(this);
        NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
        mNotificationLogger.setUpWithContainer(notifListContainer);

        mNotificationIconAreaController = SystemUIFactory.getInstance()
                .createNotificationIconAreaController(context, this, mStatusBarStateController);
        inflateShelf();
        mNotificationIconAreaController.setupShelf(mNotificationShelf);

        Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
        // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
        Dependency.get(PluginDependencyProvider.class)
                .allowPluginDependency(DarkIconDispatcher.class);
        Dependency.get(PluginDependencyProvider.class)
                .allowPluginDependency(StatusBarStateController.class);
        FragmentHostManager.get(mStatusBarWindow)
                .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
                    CollapsedStatusBarFragment statusBarFragment =
                            (CollapsedStatusBarFragment) fragment;
                    statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
                    PhoneStatusBarView oldStatusBarView = mStatusBarView;
                    mStatusBarView = (PhoneStatusBarView) fragment.getView();
                    mStatusBarView.setBar(this);
                    mStatusBarView.setPanel(mNotificationPanel);
                    mStatusBarView.setScrimController(mScrimController);

                    // CollapsedStatusBarFragment re-inflated PhoneStatusBarView and both of
                    // mStatusBarView.mExpanded and mStatusBarView.mBouncerShowing are false.
                    // PhoneStatusBarView is new instance will set to be gone in
                    // PanelBar.updateVisibility after calling mStatusBarView.setBouncerShowing
                    // that will trigger PanelBar.updateVisibility. If there is a heads up showing,
                    // it needs to notify PhoneStatusBarView is new instance to update the correct
                    // status by calling mNotificationPanel.notifyBarPanelExpansionChanged().
                    if (mHeadsUpManager.hasPinnedHeadsUp()) {
                        mNotificationPanel.notifyBarPanelExpansionChanged();
                    }
                    mStatusBarView.setBouncerShowing(mBouncerShowing);
                    if (oldStatusBarView != null) {
                        float fraction = oldStatusBarView.getExpansionFraction();
                        boolean expanded = oldStatusBarView.isExpanded();
                        mStatusBarView.panelExpansionChanged(fraction, expanded);
                    }

                    HeadsUpAppearanceController oldController = mHeadsUpAppearanceController;
                    if (mHeadsUpAppearanceController != null) {
                        // This view is being recreated, let us destroy the old one
                        mHeadsUpAppearanceController.destroy();
                    }
                    mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                            mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow);
                    mHeadsUpAppearanceController.readFrom(oldController);
                    mStatusBarWindow.setStatusBarView(mStatusBarView);
                    updateAreThereNotifications();
                    checkBarModes();
                }).getFragmentManager()
                .beginTransaction()
                .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                        CollapsedStatusBarFragment.TAG)
                .commit();
        mIconController = Dependency.get(StatusBarIconController.class);
        // 通知样式
        mHeadsUpManager = new HeadsUpManagerPhone(context, mStatusBarWindow, mGroupManager, this,
                mVisualStabilityManager);
        Dependency.get(ConfigurationController.class).addCallback(mHeadsUpManager);
        mHeadsUpManager.addListener(this);
        mHeadsUpManager.addListener(mNotificationPanel);
        mHeadsUpManager.addListener(mGroupManager);
        mHeadsUpManager.addListener(mGroupAlertTransferHelper);
        mHeadsUpManager.addListener(mVisualStabilityManager);
        mAmbientPulseManager.addListener(this);
        mAmbientPulseManager.addListener(mGroupManager);
        mAmbientPulseManager.addListener(mGroupAlertTransferHelper);
        mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
        mGroupManager.setHeadsUpManager(mHeadsUpManager);
        mGroupAlertTransferHelper.setHeadsUpManager(mHeadsUpManager);
        mNotificationLogger.setHeadsUpManager(mHeadsUpManager);
        putComponent(HeadsUpManager.class, mHeadsUpManager);
        // 引入导航栏
        createNavigationBar(result);
        ···
    }

    protected void inflateStatusBarWindow(Context context) {
        mStatusBarWindow = (StatusBarWindowView) mInjectionInflater.injectable(
                LayoutInflater.from(context)).inflate(R.layout.super_status_bar, null);
    }

super_status_bar.XML

<!-- This is the combined status bar / notification panel window. -->
<com.android.systemui.statusbar.phone.StatusBarWindowView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:sysui="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <com.android.systemui.statusbar.BackDropView
            android:id="@+id/backdrop"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone"
            sysui:ignoreRightInset="true"
            >
        <ImageView android:id="@+id/backdrop_back"
                   android:layout_width="match_parent"
                   android:scaleType="centerCrop"
                   android:layout_height="match_parent" />
        <ImageView android:id="@+id/backdrop_front"
                   android:layout_width="match_parent"
                   android:layout_height="match_parent"
                   android:scaleType="centerCrop"
                   android:visibility="invisible" />
    </com.android.systemui.statusbar.BackDropView>

    <com.android.systemui.statusbar.ScrimView
        android:id="@+id/scrim_behind"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:importantForAccessibility="no"
        sysui:ignoreRightInset="true"
        />

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

    <include layout="@layout/status_bar_expanded"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="invisible" />

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

    <com.android.systemui.statusbar.ScrimView
        android:id="@+id/scrim_in_front"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:importantForAccessibility="no"
        sysui:ignoreRightInset="true"
    />

    <LinearLayout
        android:id="@+id/lock_icon_container"
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/status_bar_height"
        android:layout_gravity="top|center_horizontal">
        <com.android.systemui.statusbar.phone.LockIcon
            android:id="@+id/lock_icon"
            android:layout_width="@dimen/keyguard_lock_width"
            android:layout_height="@dimen/keyguard_lock_height"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="@dimen/keyguard_lock_padding"
            android:contentDescription="@string/accessibility_unlock_button"
            android:src="@*android:drawable/ic_lock"
            android:scaleType="center" />
        <com.android.keyguard.KeyguardMessageArea
            android:id="@+id/keyguard_message_area"
            style="@style/Keyguard.TextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/keyguard_lock_padding"
            android:gravity="center"
            android:singleLine="true"
            android:ellipsize="marquee"
            android:focusable="true" />
    </LinearLayout>
</com.android.systemui.statusbar.phone.StatusBarWindowView>
 // TODO(b/117478341): This was left such that CarStatusBar can override this method.
    // Try to remove this.
    protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
        mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
    }

NavigationBarController 创建导航栏

    /**
     * Creates navigation bars when car/status bar initializes.
     *
     * @param includeDefaultDisplay {@code true} to create navigation bar on default display.
     */
    public void createNavigationBars(final boolean includeDefaultDisplay,
            RegisterStatusBarResult result) {
        Display[] displays = mDisplayManager.getDisplays();
        for (Display display : displays) {
            if (includeDefaultDisplay || display.getDisplayId() != DEFAULT_DISPLAY) {
                createNavigationBar(display, result);
            }
        }
    }

    /**
     * Adds a navigation bar on default display or an external display if the display supports
     * system decorations.
     *
     * @param display the display to add navigation bar on.
     */
    @VisibleForTesting
    void createNavigationBar(Display display, RegisterStatusBarResult result) {
        if (display == null) {
            return;
        }

        final int displayId = display.getDisplayId();
        final boolean isOnDefaultDisplay = displayId == DEFAULT_DISPLAY;
        final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();

        try {
            if (!wms.hasNavigationBar(displayId)) {
                return;
            }
        } catch (RemoteException e) {
            // Cannot get wms, just return with warning message.
            Log.w(TAG, "Cannot get WindowManager.");
            return;
        }
        final Context context = isOnDefaultDisplay
                ? mContext
                : mContext.createDisplayContext(display);
        NavigationBarFragment.create(context, (tag, fragment) -> {
            NavigationBarFragment navBar = (NavigationBarFragment) fragment;

            // Unfortunately, we still need it because status bar needs LightBarController
            // before notifications creation. We cannot directly use getLightBarController()
            // from NavigationBarFragment directly.
            LightBarController lightBarController = isOnDefaultDisplay
                    ? Dependency.get(LightBarController.class)
                    : new LightBarController(context,
                            Dependency.get(DarkIconDispatcher.class),
                            Dependency.get(BatteryController.class));
            navBar.setLightBarController(lightBarController);

            // TODO(b/118592525): to support multi-display, we start to add something which is
            //                    per-display, while others may be global. I think it's time to add
            //                    a new class maybe named DisplayDependency to solve per-display
            //                    Dependency problem.
            AutoHideController autoHideController = isOnDefaultDisplay
                    ? Dependency.get(AutoHideController.class)
                    : new AutoHideController(context, mHandler);
            navBar.setAutoHideController(autoHideController);
            navBar.restoreSystemUiVisibilityState();
            mNavigationBars.append(displayId, navBar);

            if (result != null) {
                navBar.setImeWindowStatus(display.getDisplayId(), result.mImeToken,
                        result.mImeWindowVis, result.mImeBackDisposition,
                        result.mShowImeSwitcher);
            }
        });
    }

这样StatusBar就创建完毕了


如有错误欢迎指出 共同学习 共同进步哈~