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

前言

上一篇我们具体分析了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();
     	...代码省略...
     }
}

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

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 {
    @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,正是我们之前多次提到的状态栏窗口对象,其内部有两个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.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中。

六、将导航栏窗口添加到Window中

1、上面我们分析完了状态栏的创建过程,下面我们再来简单分析一下系统导航栏的创建过程。

public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {

    private final NavigationBarController mNavigationBarController;//导航栏控制器

    public StatusBar(
		...代码省略...
		NavigationBarController navigationBarController,
		...代码省略...
	){
		...代码省略...
		//为导航栏控制器mNavigationBarController赋值
        mNavigationBarController = statusBarWindowController;
        ...代码省略...
    }   

    @Override
    public void start() {
    	...代码省略...
    	createAndAddWindows(result);
    	...代码省略...
    }

    public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
        makeStatusBarView(result);
        ...代码省略...
    }

   protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
		...代码省略...
        createNavigationBar(result);
        ...代码省略...
   	}
   	
    protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
        mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
    }
}

系统导航栏同样也是在StatusBar中被创建的,经过层层调用,最终是调用导航栏控制器NavigationBarController的createNavigationBars方法来创建导航栏窗口。

2、NavigationBarController的createNavigationBars方法如下所示。

frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java

public class NavigationBarController implements
        Callbacks,
        ConfigurationController.ConfigurationListener,
        NavigationModeController.ModeChangedListener,
        Dumpable {

    public void createNavigationBars(final boolean includeDefaultDisplay,
            RegisterStatusBarResult result) {
        updateAccessibilityButtonModeIfNeeded();
        // Don't need to create nav bar on the default display if we initialize TaskBar.
        final boolean shouldCreateDefaultNavbar = includeDefaultDisplay
                && !initializeTaskbarIfNecessary();
        Display[] displays = mDisplayManager.getDisplays();
        for (Display display : displays) {
            if (shouldCreateDefaultNavbar || display.getDisplayId() != DEFAULT_DISPLAY) {
                createNavigationBar(display, null /* savedState */, result);
            }
        }
    }

    void createNavigationBar(Display display, Bundle savedState, RegisterStatusBarResult result) {
        if (display == null) {
            return;
        }

        final int displayId = display.getDisplayId();
        final boolean isOnDefaultDisplay = displayId == DEFAULT_DISPLAY;

        // We may show TaskBar on the default display for large screen device. Don't need to create
        // navigation bar for this case.
        if (mIsTablet && isOnDefaultDisplay) {
            return;
        }

        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);
        NavigationBar navBar = mNavigationBarFactory.create(context);

        mNavigationBars.put(displayId, navBar);
		//调用NavigationBar的createView方法来创建导航栏并返回导航栏视图
        View navigationBarView = navBar.createView(savedState);
        navigationBarView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
            @Override
            public void onViewAttachedToWindow(View v) {
                if (result != null) {
                    navBar.setImeWindowStatus(display.getDisplayId(), result.mImeToken,
                            result.mImeWindowVis, result.mImeBackDisposition,
                            result.mShowImeSwitcher);
                }
            }

            @Override
            public void onViewDetachedFromWindow(View v) {
                v.removeOnAttachStateChangeListener(this);
            }
        });
    }
  }

NavigationBarController最终是调用NavigationBar的createView方法来创建导航栏并返回导航栏视图。

3、NavigationBar的createView方法如下所示。

public class NavigationBar implements View.OnAttachStateChangeListener,
        Callbacks, NavigationModeController.ModeChangedListener {
    public View createView(Bundle savedState) {
        mFrame = (NavigationBarFrame) LayoutInflater.from(mContext).inflate(
                R.layout.navigation_bar_window, null);
        View barView = LayoutInflater.from(mFrame.getContext()).inflate(
                R.layout.navigation_bar, mFrame);
        barView.addOnAttachStateChangeListener(this);
        mNavigationBarView = barView.findViewById(R.id.navigation_bar_view);

        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + barView);
        //将导航栏视图添加到窗口上
        mWindowManager.addView(mFrame,
                getBarLayoutParams(mContext.getResources().getConfiguration().windowConfiguration
                        .getRotation()));
        mDisplayId = mContext.getDisplayId();
        mIsOnDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;

        mCommandQueue.addCallback(this);
        mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled();
        mContentResolver = mContext.getContentResolver();
        mNavBarHelper.init();
        mAllowForceNavBarHandleOpaque = mContext.getResources().getBoolean(
                R.bool.allow_force_nav_bar_handle_opaque);
        mForceNavBarHandleOpaque = DeviceConfig.getBoolean(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                NAV_BAR_HANDLE_FORCE_OPAQUE,
                /* defaultValue = */ true);
        mHomeButtonLongPressDurationMs = Optional.of(DeviceConfig.getLong(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                HOME_BUTTON_LONG_PRESS_DURATION_MS,
                /* defaultValue = */ 0
        )).filter(duration -> duration != 0);
        DeviceConfig.addOnPropertiesChangedListener(
                DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post, mOnPropertiesChangedListener);

        if (savedState != null) {
            mDisabledFlags1 = savedState.getInt(EXTRA_DISABLE_STATE, 0);
            mDisabledFlags2 = savedState.getInt(EXTRA_DISABLE2_STATE, 0);
            mAppearance = savedState.getInt(EXTRA_APPEARANCE, 0);
            mBehavior = savedState.getInt(EXTRA_BEHAVIOR, 0);
            mTransientShown = savedState.getBoolean(EXTRA_TRANSIENT_STATE, false);
        }
        mSavedState = savedState;

        // Respect the latest disabled-flags.
        mCommandQueue.recomputeDisableFlags(mDisplayId, false);

        mIsCurrentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
        mDeviceProvisionedController.addCallback(mUserSetupListener);
        mNotificationShadeDepthController.addListener(mDepthListener);

        return barView;
    }
    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 width = WindowManager.LayoutParams.MATCH_PARENT;
        int height = WindowManager.LayoutParams.MATCH_PARENT;
        int insetsHeight = -1;
        int gravity = Gravity.BOTTOM;
        if (INSETS_LAYOUT_GENERALIZATION) {
            boolean navBarCanMove = true;
            if (mWindowManager != null && mWindowManager.getCurrentWindowMetrics() != null) {
                Rect displaySize = mWindowManager.getCurrentWindowMetrics().getBounds();
                navBarCanMove = displaySize.width() != displaySize.height()
                        && mContext.getResources().getBoolean(
                        com.android.internal.R.bool.config_navBarCanMove);
            }
            if (!navBarCanMove) {
                height = mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.navigation_bar_frame_height);
                insetsHeight = mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.navigation_bar_height);
            } else {
                switch (rotation) {
                    case ROTATION_UNDEFINED:
                    case Surface.ROTATION_0:
                    case Surface.ROTATION_180:
                        height = mContext.getResources().getDimensionPixelSize(
                                com.android.internal.R.dimen.navigation_bar_frame_height);
                        insetsHeight = mContext.getResources().getDimensionPixelSize(
                                com.android.internal.R.dimen.navigation_bar_height);
                        break;
                    case Surface.ROTATION_90:
                        gravity = Gravity.RIGHT;
                        width = mContext.getResources().getDimensionPixelSize(
                                com.android.internal.R.dimen.navigation_bar_width);
                        break;
                    case Surface.ROTATION_270:
                        gravity = Gravity.LEFT;
                        width = mContext.getResources().getDimensionPixelSize(
                                com.android.internal.R.dimen.navigation_bar_width);
                        break;
                }
            }
        }
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                width,
                height,
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
                PixelFormat.TRANSLUCENT);
        if (INSETS_LAYOUT_GENERALIZATION) {
            lp.gravity = gravity;
            if (insetsHeight != -1) {
                lp.providedInternalInsets = Insets.of(0, height - insetsHeight, 0, 0);
            } else {
                lp.providedInternalInsets = Insets.NONE;
            }
        }
        lp.token = new Binder();
        lp.accessibilityTitle = mContext.getString(R.string.nav_bar);
        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
        lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        lp.windowAnimations = 0;
        lp.setTitle("NavigationBar" + mContext.getDisplayId());
        lp.setFitInsetsTypes(0 /* types */);
        lp.setTrustedOverlay();
        return lp;
    }
 }

七、总结

最后用一张图对前面创建状态栏的代码流程做一个回顾。
在这里插入图片描述

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值