Android 12 source code analysis - application layer five (starting process of SystemUI’s StatusBar class and creation of three windows)

Android 12 source code analysis - application layer five (starting process of SystemUI’s StatusBar class and creation of three windows)

In the previous article, we introduced the basic layout and basic concepts of SystemUI App. Next, we enter how each UI of the SystemUI application is added to the screen. So let’s start with the creation of three windows.

Note: Three windows, namely StatusBar window, NavigationBar window, NotificationShade window

These three windows are all created from StatusBar.java, so we will start with this class.

This article needs to be viewed in conjunction with the previous blog post, which is an overall overview of the entire Layout. This article can be considered an overview of the entire key class.

The address of the previous blog post: "Android 12 Source Code Analysis - Application Layer Four (Basic Layout Design and Basic Concepts of SystemUI) http://t.csdn.cn/Q1XSM "

太长不想看版:
1. StatusBar的Dagger2配置 
2. StatusBar的start()函数开始初始化
3. StatusBar的start()函数调用createAndAddWindow()函数创建三大窗口
4. createAndAddWindow()函数调用makeStatusBarView()创立各个Window和View,并将其添加到屏幕上
5. makeStatusBarView()函数调用inflateStatusBarWindow()创建StatusBar和NotificationShade两个窗口
6. makeStatusBarView()函数调用createNavigationBar()创建NavigationBar窗口
7. makeStatusBarView()函数创建用在StatusBar窗口中的CollapsedStatusBarFragment它代表了StatusBar中的具体内容
8. makeStatusBarView()函数创建用在NotificationShade窗口中的QSFragment它代表了整个下拉状态栏中QS的内容

1.Dagger2 configuration of StatusBar

If you read the StatusBar source code carefully, you will find that the constructor of StatusBar is not marked with the @Inject annotation. Then the StatusBar will not be automatically created. But in order to better join the Dagger2 diagram, we provide the StatusBar object through @Provides. as follows:

@Module(includes = {
    
    StatusBarPhoneDependenciesModule.class})
public interface StatusBarPhoneModule {
    
    
    //提供StatusBard对象实例
    @Provides
    @SysUISingleton
    static StatusBar provideStatusBar(
            Context context,
            /*省略超级长的参数定义*/) {
    
    
        return new StatusBar(
                context,
                /*省略超级长的参数传入*/);
    }
}

From the above code, we can get: The StatusBarPhoneModule module provides a method to create a StatusBar. That is, when SystemUI requires StatusBar, it will be provided by the provideStatusBar method.

In the constructor of StatusBar, it is just a simple object assignment, no need to go into details. As for the logical abstractions corresponding to these objects, we will further mention them when using them.

Note: For an explanation of @Provides and how Dagger2 implements provideStatusBar and StatusBarPhoneModule, see "Android 12 Source Code Analysis - Application Layer Three (SystemUIFactory and its Dependency Analysis) http://t.csdn.cn/1o4P3 "

Then StatusBarPhoneModule will definitely be included in SysUIComponent. Let's sort out the relationship between them.

Search the entire source code of SystemUI and you can see the following code:

//可见StatusBarModule模块包含了 StatusBarPhoneModule模块
@Module(includes = {
    
    StatusBarPhoneModule.class, StatusBarDependenciesModule.class,
        NotificationsModule.class, NotificationRowModule.class})
public interface StatusBarModule {
    
    
}

The StatusBarModule module is included in the SystemUIBinder module, as follows:

//包含StatusBarModule模块
@Module(includes = {
    
    RecentsModule.class, StatusBarModule.class, KeyguardModule.class})
public abstract class SystemUIBinder {
    
    }

The SystemUIBinder module is included by SystemUIComponent as follows:

//包含SystemUIBinder模块
@SysUISingleton
@Subcomponent(modules = {
    
    
        DefaultComponentBinder.class,
        DependencyProvider.class,
        SystemUIBinder.class,
        SystemUIModule.class,
        SystemUIDefaultModule.class})
public interface SysUIComponent {
    
    }

Let us summarize its inclusion relationship:

SysUIComponent > SystemUIBinder > StatusBarModule > StatusBarPhoneModule:提供创建StatusBar实例的方法 

2.The first opportunity to create StatusBar

When system_server starts SystemUIService, it will enable the startServicesIfNeeded() function of SystemUIApplication.

In this function, the corresponding service will be started based on the configuration parameters. Among them, StatusBar is in the configuration. Once the configuration is read, the resolveSystemUI of ContextComponentHelper is called to query whether the corresponding object can be provided in Dagger2. This is the time when StatusBar was first founded.

For the specific process of this part, see: "Android 12 Source Code Analysis - Application Layer 2 (General Organization and Startup Process of SystemUI) http://t.csdn.cn/Gk418 " startServicesIfNeeded() function

In order to have an intuitive feeling, here is a picture of the call stack created for the first time. as follows

Insert image description here

Note: For details on obtaining the call stack, see: "Android 12 Source Code Analysis - Application Layer 1 (SystemUI Preparation) http://t.csdn.cn/FrjAh " (This is a must-read article, please be sure to master it techniques and methods)

3. Initialization of StatusBar

After being created in the startServicesIfNeeded() function of SystemUIApplication, the two methods of SystemUI will be called immediately, and StatusBar inherits SystemUI, so these two methods will also be called:

  1. First call the start() method
  2. Then call the onBootCompleted() method

Looking at the StatusBar, you will find that it does not override the onBootCompleted() method. Then the initialization of StatusBar will only have the start() method

4. StatusBar.start() function

The StatusBar.start() function is particularly long. The source code is as follows:

Note: This article focuses on its startup process and will not introduce too many specific details of each class. For example, it will not introduce the detailed design logic of ScreenLifeCycle. These detailed design logic will be introduced in chapters after the entire startup process is introduced.

@Override
    public void start() {
    
    
        //监听屏幕的生命周期,屏幕的生命周期有:正在打开,打开完成,正在关闭,关闭完成
        mScreenLifecycle.addObserver(mScreenObserver);
        //监听设备的唤醒和睡眠,注意它和Doze模式的区别
        mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
        //赋值UIModeManager,它提供,disable car mode等功能
        mUiModeManager = mContext.getSystemService(UiModeManager.class);
        //对BypassHeadsUpNotifier进行初始化,它可以绕过heads up。
        //heads up的解释见后文补充内容
        mBypassHeadsUpNotifier.setUp();
        //如果当前存在气泡通知,则监听taskbar的改变
        //气泡通知。见后文补充内容
        if (mBubblesOptional.isPresent()) {
    
    
            mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
            IntentFilter filter = new IntentFilter(TASKBAR_CHANGED_BROADCAST);
            mBroadcastDispatcher.registerReceiver(mTaskbarChangeReceiver, filter);
        }

        //初始化KeyguardIndicationController,它控制锁屏底部消息的提示,如对充电的提示
        mKeyguardIndicationController.init();

        //颜色提取器,增加监听,一旦颜色改变SystemUI会进行相应的主题切换
        mColorExtractor.addOnColorsChangedListener(this);
        //监听StatusBarState的改变,当StatusBarSate改变时,将会收到通知。
        //注意监听器,有优先级
        //StatusBarState在当前版本有4中状态:1. SHADE(也就是正常状态,卷帘(也即下拉状态栏)被收起的状态)
        //2. KEYGUARD(StatusBar当前处在锁屏状态)
        //3. SHADE_LOCKED(StatusBar当前在锁屏装来下,被下拉出来了)
        //4. FULLSCREEN_USER_SWITCHER(statusbar被锁住,同时展示一个全屏的多用户切换)
        mStatusBarStateController.addCallback(this,
                SysuiStatusBarStateController.RANK_STATUS_BAR);

        //赋值WindwManager
        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        //赋值DreamManager,它和屏保有关,注意它和后面Ambient mode的区别
        mDreamManager = IDreamManager.Stub.asInterface(
                ServiceManager.checkService(DreamService.DREAM_SERVICE));

        //赋值,mDisplay对象,Display对象代表了一种逻辑屏幕,而非实体屏幕
        mDisplay = mWindowManager.getDefaultDisplay();
        mDisplayId = mDisplay.getDisplayId();
        //更新需要的DisplaySize相关信息
        updateDisplaySize();

        //读取配置,查看是否打开震动
        mVibrateOnOpening = mContext.getResources().getBoolean(
                R.bool.config_vibrateOnIconAnimation);

        //赋值WindowManagerService,注意前面已经获取到了WindowManager。
        //事实上,这个根本没有在本类中使用,它只是以前老旧代码的遗产
        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
        //获取DevicePolicyManager,它是设备所有者规定的一些策略,比如是否允许当前用户使用相机等等
        mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
                Context.DEVICE_POLICY_SERVICE);

        //赋值,辅助功能,本类中也未使用该变量,它是以前代码的遗产
        mAccessibilityManager = (AccessibilityManager)
                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);

        //为KeyguardUpdateMonitor设置一个KeyguardBypassController
        //其中KeyguradUpdateMonitor负责监听Keyguard感兴趣的事情,比如SIM卡的变化等
        //KeyguardBypassController负责绕过锁屏的控制,比如人脸识别,识别正确,则直接打开锁屏(注意,此类我不是很确定)
        mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
        //获取StatusBarManagerService。注意StatusBarManagerService和StatusBar之间的关系,见后文补充内容
        mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));

        //获取KeyguardManager,该类用于解锁和加锁keyguard
        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);

        //检查当前用户是否支持设置和查询Wallpaper(壁纸)
        mWallpaperSupported =
                mContext.getSystemService(WallpaperManager.class).isWallpaperSupported();

        //CommandQueue增加一个回调,关于CommandQueue的说明,见补充知识点
        mCommandQueue.addCallback(this);

        //监听DemoMode。DemoMode的知识点,见补充内容
        mDemoModeController.addCallback(this);

        //根据补充内容第三点和第四点,需要建立和sytem_server进程中的StatusBarManagerService之间的联系
        //返回结果包括系统要求的一些东西,如显示哪些图标,禁用哪些功能等
        RegisterStatusBarResult result = null;
        try {
    
    
            result = mBarService.registerStatusBar(mCommandQueue);
        } catch (RemoteException ex) {
    
    
            ex.rethrowFromSystemServer();
        }

        //现在开始创建UI,这个就是在上一篇博文中,提及的UI布局和创建的入口
        //下文详解
        createAndAddWindows(result);

        //如果mWallpaperSupported为true,也即当前用户支持访问和修改壁纸
        if (mWallpaperSupported) {
    
    
            //那么监听壁纸的改变
            IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
            mBroadcastDispatcher.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter,
                    null /* handler */, UserHandle.ALL);
            //注意,此处主动调用了onRecive()函数,它是为了初始化其他Controller中关于
            //壁纸的一些信息,如,设置NotificationShadeWindowController是否支持Ambient模式,Ambient mode见后文
            mWallpaperChangedReceiver.onReceive(mContext, null);
        } else if (DEBUG) {
    
    
            //or,we log the message
            Log.v(TAG, "start(): no wallpaper service ");
        }

        //初始化各个presenter后文详细介绍
        setUpPresenter();

        //检查Result对象是否要求显示一个临时的StatusBar,这往往是来自于system_server的请求
        //临时的StatusBar对于用户来讲是临时可见的
        if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) {
    
    
            //显示一个临时的StatusBar,它通过显示一个StatusBar的过渡动画来显示
            showTransientUnchecked();
        }

        //一旦获取到RegisterStatusBarResult对象(后文称:Result对象),我们就要根据其
        //内容进行相应的设置。
        //用于通知SystemBar的一些属性已经改变。因为这些属性以前没有被设置过
        onSystemBarAttributesChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions,
                result.mNavbarColorManagedByIme, result.mBehavior, result.mAppFullscreen);

        //通知输入法的状态改变,但是此处内容为空。
        setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis,
                result.mImeBackDisposition, result.mShowImeSwitcher);

        //将图标信息,通过CommandQueue通知给感兴趣的对象
        int numIcons = result.mIcons.size();
        for (int i = 0; i < numIcons; i++) {
    
    
            //在该队列中,会调用callback通知其他需要处理图标的对象
            mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i));
        }
        //省略调试代码

        //如果当前用户支持设置壁纸
        if (mWallpaperSupported) {
    
    
            //那么就设置壁纸不要处于Ambient模式,ambient mode是关屏之后,屏幕显示一些
            //画面和周围的环境融为一体,如,在电视上显示一副梵高的星空,当做整面墙的装饰
            //被称为:环境融合模式
            IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
                    ServiceManager.getService(Context.WALLPAPER_SERVICE));
            try {
    
    
                //set in ambient mode
                wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */);
            } catch (RemoteException e) {
    
    
                // Just pass, nothing critical.
            }
        }

        //图标显示的策略,哪些该显示,哪些不该显示
        mIconPolicy.init();

        //监听锁屏状态
        mKeyguardStateController.addCallback(this);
        //初始化锁屏相关对象
        startKeyguard();

        //StatusBar也需要监听一些外部消息,这些外部消息也是Keyguard感兴趣的消息,如SIM卡的状态改变
        mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);

        //初始化DozeServiceHost,它和Doze 模式相关,是DozeService和SystemUI其他部分交互的接口。后面文章详细讲解
        mDozeServiceHost.initialize(
                this,
                mStatusBarKeyguardViewManager,
                mNotificationShadeWindowViewController,
                mNotificationPanelViewController,
                mAmbientIndicationContainer);
        //在Doze模式下,还有很多配置参数,DozeParameters就是配置参数的逻辑抽象,此处给他增加一个监听
        mDozeParameters.addCallback(this::updateLightRevealScrimVisibility);

        //监听配置的改变,如语言改变,时区改变等
        mConfigurationController.addCallback(this);

        //监听电池相关的信息
        mBatteryController.observe(mLifecycle, this);
        mLifecycle.setCurrentState(RESUMED);

        //初始化disableFlag相关的内容
        //disableFlag相关的内容见后文的补充内容
        int disabledFlags1 = result.mDisabledFlags1;
        int disabledFlags2 = result.mDisabledFlags2;
        //调用InitController,初始化disablFlag相关的内容
        //InitController收集,所有在SystemUI实现类启动完成之后,的任务
        //然后在SystemUIApplication的startServicesIfNeeded()函数中被调用
        //此处通过调用setUpDisableFlags()函数,来处理disableFlags
        //而setUpDisableFlags()函数,通过CommandQueue将需要处理的disableFlags通知给其他需要的对象。比如告诉NavigationBar不要显示recent        
        mInitController.addPostInitTask(
                () -> setUpDisableFlags(disabledFlags1, disabledFlags2));

        //增加误触的监听,当发生误触时,需要复位一些UI,防止一些动画停止在半途
        //Falsingmanager负责管理,一些误触的操作
        mFalsingManager.addFalsingBeliefListener(mFalsingBeliefListener);

        //给PluginManager,增加一个插件监听器。插件相关内容不做介绍,后面详细介绍
        mPluginManager.addPluginListener(/*省略代码*/}

The start() function mainly completes the following functions:

  1. Initialize each business class related to the entire SystemUI App
  2. Establish reference relationships between these
  3. Initialize the configuration in StatusBarManagerService, such as disablFlag, icon, transient bar, etc.
  4. Call createAndAddWindow() to create the required UI

Next, we start with the createAndAddWindow() function and look at the process of creating the UI.

Basic concept supplement

  1. heads up: A notification display method of SystemUI that allows important notifications to appear at the top of the screen in the form of cards.
  2. Bubble notification: Bubble notification is a notification display method that floats on the screen, such as the text message content received by Messages by google
  3. The relationship between StatusBar and StatusBarManagerService: As an application, SystemUI cannot be used by other users. In order to ensure the use of other users, there is a StatusBarService service inside the system, which is located in the system_server process. It is responsible for interacting with other users. At the same time, when SystemUI is started, it will register itself in the StatusBarSerivce service. In this way, the StatusBarService service can call the StatusBar function in SystemUI. The simple structure is as follows: SystemUI<---->StatusBarManagerService<----->other app. In order to communicate smoothly between them, binder communication is used.
  4. CommandQueue: In the third point, we mentioned that StatusBarManagerService and SystemUI communicate through Binder. When SystemUI wants to call StatusBarManagerService, it uses the IStatusBarService interface. When StatusBarManagerService calls SystemUI, it uses the IStatusBar interface. The implementation of this interface on the SystemUI side is CommandQueue. ComandQueue can be understood as: a command queue from the outside (relative to the outside of SystemUI).
  5. DemoMode: Demo mode. Demo mode will fix a fake statusbar, which can be used to debug the UI of each icon. Regarding the further opening and closing instructions of DemoMode, we will mention it in detail later.
  6. disableFlags: It represents the functions that should be disabled in SystemUI. It is divided into two types, disable1 and disable2. If other processes need to modify the values ​​​​of these two, they can use the disablexxx() function of IStatusBarService to modify it.
    • The values ​​of disable1 are:
      • DISABLE_NONE: Disable nothing
      • DISABLE_EXPAND: Disable drop-down expansion
      • DISABLE_NOTIFICATION_ICONS: Disable notification icons
      • DISABLE_NOTIFICATION_ALERTS: Disable notification sounds, vibrations, pop-up alerts and other functions
      • DISABLE_NOTIFICATION_TICKER: Disable notification scroll bar
      • DISABLE_SYSTEM_INFO: Disable information display in the middle area of ​​the status bar
      • DISABLE_HOME/RECENT/BACK: Disable the home, recent, and BACK buttons in the navigation bar respectively
      • DISABLE_CLOCK: Disable the clock display in the status bar
      • DISABLE_SEARCH: Disable search
      • DISABLE_ONGOING_CALL_CHIP: Disable the calling icon in the status bar
    • The values ​​of disable2 are:
      • DISABLE_NONE: Disable nothing
      • DISABLE_QUICK_SETTINGS: Disable QS
      • DISABLE_SYSTEM_ICON: Disable system icon
      • DISABLE_NOTIFICATION_SHADE: Disable NotificationShade window
      • DISABLE_GLOBAL_ACTION: Disable GlobalActionDialog, that is, turn on and off the pop-up box
      • DISABLE_ROTATE_SUGGESTIONS: Disable rotation suggestion icons in the navigation bar
  7. Ambient mode: ambient mode is when the screen is turned off, and some images displayed on the screen are integrated with the surrounding environment. For example, a Van Gogh's starry sky is displayed on the TV as a decoration for the entire wall. It is called: ambient fusion mode
    Insert image description here

4.1 createAndAddWindwo() function

The original text of the createAndAddWindow() function is as follows:

public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
    
    
    //创建对应的UI
    makeStatusBarView(result);
    //将NotificationShadeWindow加入屏幕
    mNotificationShadeWindowController.attach();
    //将StatusBarWinidow加入屏幕
    mStatusBarWindowController.attach();
}

Note: For instructions on NotificationShadeWindow and StatusBarWindow, see "Android 12 Source Code Analysis - Application Layer Four (Basic Layout Design and Basic Concepts of SystemUI) http://t.csdn.cn/ioWFS "

Next, take a look at the makeStatusBarView() function

4.1.1 makeStatusBarView() function

The makeStatusBarView() function is responsible for creating the Views of the three major windows. The source code is as follows:

protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
    
    
    //更新需要用到的资源,如逻辑屏幕的大小
    final Context context = mContext;
    updateDisplaySize(); // populates mDisplayMetrics
    //更新资源,在还没有创建各种View之前,该函数实际调用为空
    updateResources();
    //更新主题
    updateTheme();

    //构造真正的View视图,见后文详解
    inflateStatusBarWindow();
    //NotificationShadeWindowViewController是NotificationShadeWindowView的控制器
    //而这个View是NotificationShade窗口的顶层窗口
    mNotificationShadeWindowViewController.setService(this, mNotificationShadeWindowController);
    //为其设置一个触摸监听
    mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener());

    //分别找到View层级中的各个view的Controller
    mStackScrollerController =
            mNotificationPanelViewController.getNotificationStackScrollLayoutController();
    mStackScroller = mStackScrollerController.getView();
    NotificationListContainer notifListContainer =
            mStackScrollerController.getNotificationListContainer();
    //并将NotificationListContainer设置到NotificationLogger中
    mNotificationLogger.setUpWithContainer(notifListContainer);

    //构造NotificationShelf视图
    inflateShelf();
    //将Shelf中的icon和状态栏中的icon同步一一下
    mNotificationIconAreaController.setupShelf(mNotificationShelfController);
    //为NotificationPanelView设置监听器,监听展开的过程
    mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator);
    mNotificationPanelViewController.addExpansionListener(
            this::dispatchPanelExpansionForKeyguardDismiss);

    // 允许Plugin引用DarkDispatcher和StatusBarStateController
    mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class);
    mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
    //使用Fragment管理StatusBar的View,达到可重用的目的
    //注意:对于这里提及的各个View,可以查看上一篇关于Layout基本布局的博文
    FragmentHostManager.get(mPhoneStatusBarWindow)
            .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
    
    
                //将Fragment转换成CollapsedStatusBarFragment
                CollapsedStatusBarFragment statusBarFragment =
                        (CollapsedStatusBarFragment) fragment;

                //先保存以前的PhoneStatusBarView
                PhoneStatusBarView oldStatusBarView = mStatusBarView;
                //再获取新的PhoneStatusBarView
                mStatusBarView = (PhoneStatusBarView) statusBarFragment.getView();
                //对PhoneStatusBarView进行设置,包括注册监听,传递需要的对象等
                mStatusBarView.setBar(this);
                mStatusBarView.setPanel(mNotificationPanelViewController);
                mStatusBarView.setScrimController(mScrimController);
                mStatusBarView.setExpansionChangedListeners(mExpansionChangedListeners);

                //如果有一个heads up在顶部,则需要调整为正确的状态
                if (mHeadsUpManager.hasPinnedHeadsUp()) {
    
    
                    //主要是通知各个监听器,更新各自的状态
                    mNotificationPanelViewController.notifyBarPanelExpansionChanged();
                }
                //初始化PhoneStatusBarView中的Bouncer
                //Bouncer界面就是,解锁时要求输入pin,密码等的界面
                //新创建的PhoneStatusBarView中的Bouncer默认是没有打开的。因此要根据
                //当前实际进行更新
                mStatusBarView.setBouncerShowing(mBouncerShowing);
                //如果以前的StatusBar已经展开了一部分,则要求新的StatusBar也展开同样的大小
                //因为新创建的PhoneStatusBar,默认展开是0
                if (oldStatusBarView != null) {
    
    
                    float fraction = oldStatusBarView.getExpansionFraction();
                    boolean expanded = oldStatusBarView.isExpanded();
                    mStatusBarView.panelExpansionChanged(fraction, expanded);
                }

                //重新创建HeadsUpAppearanceController
                HeadsUpAppearanceController oldController = mHeadsUpAppearanceController;
                if (mHeadsUpAppearanceController != null) {
    
    
                    mHeadsUpAppearanceController.destroy();
                }
                //重新创建一个新的HeadsUpAppearanceController对象
                //这个对象负责控制heads up的外观
                mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                        mNotificationIconAreaController, mHeadsUpManager,
                        mStackScroller.getController(),
                        mStatusBarStateController, mKeyguardBypassController,
                        mKeyguardStateController, mWakeUpCoordinator, mCommandQueue,
                        mNotificationPanelViewController, mStatusBarView);
                //从旧对象中读取值赋值给新对象
                mHeadsUpAppearanceController.readFrom(oldController);
                
                //建立LightsOutNotificationController和对应View的关系
                //LightsOutNotificationController表示的是暗模式
                mLightsOutNotifController.setLightsOutNotifView(
                        mStatusBarView.findViewById(R.id.notification_lights_out));
                //将StatusBar窗口的view,放入NotificationShade窗口的控制器中
                mNotificationShadeWindowViewController.setStatusBarView(mStatusBarView);
                //检查是否要进行StatusBar的模式切换,如果要切换则会形成一个过渡动画
                //关于StatusBar模式切换的细节,我们在介绍完StatusBarWindow的整个初始化过程之后,
                //另外的文章进一步介绍.此处我们关注整个启动过程
                checkBarModes();
            }).getFragmentManager()
            .beginTransaction()
            .replace(R.id.status_bar_container,
                    new CollapsedStatusBarFragment(
                            mOngoingCallController,
                            mAnimationScheduler,
                            mStatusBarLocationPublisher,
                            mNotificationIconAreaController,
                            mFeatureFlags,
                            mStatusBarIconController,
                            mKeyguardStateController,
                            mNetworkController,
                            mStatusBarStateController,
                            this,
                            mCommandQueue
                    ),
                    CollapsedStatusBarFragment.TAG)
            .commit();

    //设置必要的对象,这些对象的功能和逻辑抽象,在必要的时候介绍.
    //现在,大体可按照如下的方式进行理解
    //HeadsUpManager:负责管理heads up,如管理Heads up通知的更新
    //VisualStabilityManager:保证一种固定的通知显示,当通知超出显示范围的时候,就抑制其重排
    //StatusBarTouchableRegionManager:管理StatusBar的哪一部分可以触摸
    mHeadsUpManager.setup(mVisualStabilityManager);
    mStatusBarTouchableRegionManager.setup(this, mNotificationShadeWindowView);
    mHeadsUpManager.addListener(this);
    mHeadsUpManager.addListener(mNotificationPanelViewController.getOnHeadsUpChangedListener());
    mHeadsUpManager.addListener(mVisualStabilityManager);
    mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);

    //构建NavigationBar
    createNavigationBar(result);

    //ENABLE_LOCKSCREEN_WALLPAPER 是否打开锁屏下显示壁纸,默认打开
    //mWallpaperSupported表示当前用户是否支持设置和访问壁纸,默认支持
    if (ENABLE_LOCKSCREEN_WALLPAPER && mWallpaperSupported) {
    
    
        //得到LockScreenWallpaper对象
        mLockscreenWallpaper = mLockscreenWallpaperLazy.get();
    }


    //传递必要的对象
    mNotificationPanelViewController.setKeyguardIndicationController(
            mKeyguardIndicationController);

    //这是负责显示Ambient模式的视图,但是在当前版本中是没有实现的
    //目前可以在三星的电视机上有这部分的实现代码
    //本系列文章将不会介绍
    mAmbientIndicationContainer = mNotificationShadeWindowView.findViewById(
            R.id.ambient_indication_container);

    //控制自动隐藏的UI元素,当需要判断是否要自动隐藏式,需要查询当前的StatusBar的一些状态
    //故要调用setStatusBar传递过去,此处对StatusBar的函数封装成了AutoHideUiElement对象
    mAutoHideController.setStatusBar(new AutoHideUiElement() {
    
    
        @Override
        public void synchronizeState() {
    
    
            checkBarModes();
        }

        @Override
        public boolean shouldHideOnTouch() {
    
    
            return !mRemoteInputManager.getController().isRemoteInputActive();
        }

        @Override
        public boolean isVisible() {
    
    
            return isTransientShown();
        }

        @Override
        public void hide() {
    
    
            clearTransient();
        }
    });

    //查找遮罩
    //关于遮罩的说明,见上一篇Layout基本布局的博文
    ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind);
    ScrimView notificationsScrim = mNotificationShadeWindowView
            .findViewById(R.id.scrim_notifications);
    ScrimView scrimInFront = mNotificationShadeWindowView.findViewById(R.id.scrim_in_front);
    ScrimView scrimForBubble = mBubblesManagerOptional.isPresent()
            ? mBubblesManagerOptional.get().getScrimForBubble() : null;

    //设置遮罩的监听
    mScrimController.setScrimVisibleListener(scrimsVisible -> {
    
    
        mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible);
    });

    //将遮罩的controller和view进行连接
    mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront, scrimForBubble);

    //找到LightRevealScrim,关于LightRevealScrim见上一篇关于Layout基本布局的博文
    mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
    //设置透明度改变的监听
    mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> {
    
    
        Runnable updateOpaqueness = () -> {
    
    
            mNotificationShadeWindowController.setLightRevealScrimOpaque(
                    mLightRevealScrim.isScrimOpaque());
        };
        if (opaque) {
    
    
            // Delay making the view opaque for a frame, because it needs some time to render
            // otherwise this can lead to a flicker where the scrim doesn't cover the screen
            mLightRevealScrim.post(updateOpaqueness);
        } else {
    
    
            updateOpaqueness.run();
        }
    });
    //初始化用于AOD动画的controller,AOD概念见补充知识
    mUnlockedScreenOffAnimationController.initialize(this, mLightRevealScrim);
    //根据配置,进行LightRevealScrim的可见性的设置
    updateLightRevealScrimVisibility();

    //为NotificationPanelViewController设置必要的对象
    mNotificationPanelViewController.initDependencies(
            this,
            mNotificationShelfController);

    //找到BackDropView,BackDropView的说明见上一篇关于Layout布局的博文
    BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
    //因为多媒体播放时,可能会使用BackDropView,因此将BackDropView传递给NotificationMediaManager
    mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
            backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper);
    //读取配置,获取最大的壁纸放大系数,默认值为1.10
    float maxWallpaperZoom = mContext.getResources().getFloat(
            com.android.internal.R.dimen.config_wallpaperMaxScale);
    //NotificationShadeDepthController负责statusbar 窗口的模糊
    //此处增加一个监听器,监听模糊的程度,越模糊则depth越大
    mNotificationShadeDepthControllerLazy.get().addListener(depth -> {
    
    
        float scale = MathUtils.lerp(maxWallpaperZoom, 1f, depth);
        backdrop.setPivotX(backdrop.getWidth() / 2f);
        backdrop.setPivotY(backdrop.getHeight() / 2f);
        backdrop.setScaleX(scale);
        backdrop.setScaleY(scale);
    });
    //通知NotificationPanelViewController此时此刻,还未走完开机向导
    mNotificationPanelViewController.setUserSetupComplete(mUserSetup);

    //获取qs_frame,该view用于放置QS,关于QS,见补充内容
    final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame);
    if (container != null) {
    
    
        //使用Fragment创建一个可以被复用的View,该Fragment用于放置QS
        FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
        //辅助类,创建QSFragment对象,然后提交到FragmentManager中
        ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
                mExtensionController
                        .newExtension(QS.class)
                        .withPlugin(QS.class)
                        .withDefault(this::createDefaultQSFragment)
                        .build());
        //创建BrightnessMirrorController
        mBrightnessMirrorController = new BrightnessMirrorController(
                mNotificationShadeWindowView,
                mNotificationPanelViewController,
                mNotificationShadeDepthControllerLazy.get(),
                mBrightnessSliderFactory,
                (visible) -> {
    
    
                    mBrightnessMirrorVisible = visible;
                    updateScrimController();
                });
        //触发FragmentManager中的onFragmentViewCreated方法,并在触发之后,
        //传递需要的对象
        fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
    
    
            QS qs = (QS) f;
            if (qs instanceof QSFragment) {
    
    
                mQSPanelController = ((QSFragment) qs).getQSPanelController();
                mQSPanelController.setBrightnessMirror(mBrightnessMirrorController);
            }
        });
    }

    //省略调试功能代码

    //如果未亮屏幕
    //那么主动触发一个ACTION_SCREEN_OFF的操作,后文详解这个操作
    if (!mPowerManager.isScreenOn()) {
    
    
        mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
    }
    //创建一个唤醒锁。
    mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
            "GestureWakeLock");
    //获取震动服务
    mVibrator = mContext.getSystemService(Vibrator.class);
    //VibrationEffect用于表示触摸震动的视觉效果
    mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect(
            mVibrator, context.getResources());

    //注册广播接收器
    //监听,请求NotificationShadeWindow消失的Intent
    //监听,请求Recent消失的Intent
    //监听,屏幕关闭
    //监听,请求StatusBar 打开设备monitoring dialog
    registerBroadcastReceiver();

    //去掉用于调试的代码

    //监听用户是否已经设置完,开机向导
    mDeviceProvisionedController.addCallback(mUserSetupObserver);
    //主动调用,用于调用setUserSetupComplete为正确的值
    mUserSetupObserver.onUserSetupChanged();

    //下面两句代码,用于hwui库,暂时不用管
    // disable profiling bars, since they overlap and clutter the output on app windows
    ThreadedRenderer.overrideProperty("disableProfileBars", "true");

    // Private API call to make the shadows look better for Recents
    ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
}

This method completes the following functions:

  1. Initialize various resources
  2. Call inflateStatusBarWindow() to construct the top-level View container of the NotificationShade window and the StaturBar window
  3. Call inflateShelf() to construct NotificationShelf
  4. Call createNavigationBar() to construct the top-level View container of the NavigationBar window
  5. Then create a reusable View through Fragment and add it to these top-level container Views, such as QSFragment, CollapsedStatusBarFragment
  6. Create the connection between Controller and View again
  7. Register for broadcasts of interest

Basic concept supplement

  1. AOD: always on display, SystemUI provides a UI that will be displayed when the screen is off.
  2. QS: Quick Settings, which is a row of icons that can be quickly switched on and off after pulling down the status bar.
  3. Wake lock: Obtain a WakeLock object by calling PowerManager's newWakeLock(). To lock, call WakeLock.acquire(), to release, call WakeLock.release(). WakeLock can be configured with different lock levels, mainly including:
    • PARTIAL_WAKE_LOCK: Partial wake lock, screen and keyboard backlight can be turned off, but the CPU will continue to run until release is called
    • FULL_WAKE_LOCK: Full wake lock, the CPU is always running, and the screen and keyboard backlight will not be turned off.
    • SCREEN_DIM_WAKE_LOCK: Screen dimming wake-up lock, the screen is always on, but will dim, and the keyboard backlight is allowed to be turned off. Pressing the power button will release the lock
    • SCREEN_BRIGHT_WAKE_LOCK: The screen will not dim and the keyboard backlight is allowed to be turned off. If you press power, the lock will be released

Next we introduce two functions used to create top-level Views, inflateStatusBarWindow() and createNavigationBar()

4.1.1.1 inflateStatusBarWindow() function

The function source code is as follows:

private void inflateStatusBarWindow() {
    
    
    //通过工厂类,得到NotificationShade窗口的顶层View,细节见后文补充
    mNotificationShadeWindowView = mSuperStatusBarViewFactory.getNotificationShadeWindowView();
    //根据Dagger2中画的图,获取各个需要的对象,Dagger2的细节见“Android 12 源码分析 —— 应用层 三”
    StatusBarComponent statusBarComponent = mStatusBarComponentBuilder.get()
            .statusBarWindowView(mNotificationShadeWindowView).build();
    //获取需要的依赖
    mNotificationShadeWindowViewController = statusBarComponent
            .getNotificationShadeWindowViewController();
    //建立view和controller之间的联系
    mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
    //创建完顶层View之后,需要创建子View,本方法用于创建子View。这个过程将会在后续文章“NotificationShade窗口”中介绍
    mNotificationShadeWindowViewController.setupExpandedStatusBar();
    //获取依赖并初始化
    mStatusBarWindowController = statusBarComponent.getStatusBarWindowController();
    //根据工厂类,获取StatusBar窗口的顶层View,细节见后文补充
    mPhoneStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView();
    //获取依赖,并初始化
    mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController();
    statusBarComponent.getLockIconViewController().init();

    //依然是获取依赖并初始化
    mAuthRippleController = statusBarComponent.getAuthRippleController();
    mAuthRippleController.init();
}

In this function inflateStatusBarWindow(), the main work done is:

  1. Create the top-level View and initialize it
  2. Establish the connection between Controller and View

Let’s first look at how the above function creates the top-level View of NotificationShadeWindow.

The getNotificationShadeWindow() of SuperStatusBarViewFactory is as follows

public NotificationShadeWindowView getNotificationShadeWindowView() {
    
    
    if (mNotificationShadeWindowView != null) {
    
    
        return mNotificationShadeWindowView;
    }

    //解析,super_notification_shade.xml文件。 super_notification_shade.xml文件见“Android 12 源码分析 —— 应用层 四”
    mNotificationShadeWindowView = (NotificationShadeWindowView)
            mInjectionInflationController.injectable(
            LayoutInflater.from(mContext)).inflate(R.layout.super_notification_shade,
            /* root= */ null);
    if (mNotificationShadeWindowView == null) {
    
    
        throw new IllegalStateException(
                "R.layout.super_notification_shade could not be properly inflated");
    }

    return mNotificationShadeWindowView;
}

Note: For a detailed description of the super_notification_shade.xml file, see "Android 12 Source Code Analysis - Application Layer Four (Basic Layout Design and Basic Concepts of SystemUI) http://t.csdn.cn/Jmtwu "

Next, you need to take a look at how the top-level View of the StatusBar window is created. The source code is as follows:

public StatusBarWindowView getStatusBarWindowView() {
    
    
    if (mStatusBarWindowView != null) {
    
    
        return mStatusBarWindowView;
    }

    //解析super_status_bar.xml文件,并返回。
    //super_status_bar.xml文件的详细说明,见上一篇博文“Android 12 源码分析 —— 应用层 四”
    mStatusBarWindowView =
            (StatusBarWindowView) mInjectionInflationController.injectable(
            LayoutInflater.from(mContext)).inflate(R.layout.super_status_bar,
            /* root= */ null);
    if (mStatusBarWindowView == null) {
    
    
        throw new IllegalStateException(
                "R.layout.super_status_bar could not be properly inflated");
    }
    return mStatusBarWindowView;
}

Summary: inflateStatusBarWindow() method, used to create the top-level View of two windows (StatusBar and NotificationShade)

Note: This article mainly focuses on the initialization process of the StatusBar class. The details after each top-level View and the details of the corresponding sub-View will be introduced in detail in the corresponding chapters.

4.1.1.2 createNavigationBar() function

The source code of createNavigationBar() is as follows:

protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
    
    
    //调用控制器方法,创建相应的View和Window
    //在此处我们只需要知道是干什么的就行,在后面的文章中会详细介绍NavigationBar的创建
    mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
}

Note: The topic of this article is the startup process of StatusBar and the initial creation of three windows. In subsequent articles, we will discuss the creation process of each window in detail.

4.1.1.3 Actively trigger ACTION_SCREEN_OFF for the first time

In the makeStatusBarView() function, the onReceive method of the broadcast receiver is actively called and an Intent of ACTION_SCREEN_OFF is passed.

Next we look at the operations corresponding to this action.

private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    
    
    @Override
    public void onReceive(Context context, Intent intent) {
    
    
        Trace.beginSection("StatusBar#onReceive");
        if (DEBUG) Log.v(TAG, "onReceive: " + intent);
        String action = intent.getAction();
        //省略跟SCREEN_OFF无关的代码
        if (Intent.ACTION_SCREEN_OFF.equals(action)) {
    
    
            //设置其可触摸
            if (mNotificationShadeWindowController != null) {
    
    
                mNotificationShadeWindowController.setNotTouchable(false);
            }
            //如果有气泡通知,则隐藏
            if (mBubblesOptional.isPresent() && mBubblesOptional.get().isStackExpanded()) {
    
    
                // Post to main thread handler, since updating the UI.
                mMainThreadHandler.post(() -> mBubblesOptional.get().collapseStack());
            }
            //结束StatusBar和NavigationBar的过渡动画
            finishBarAnimations();
            //通知变成折叠状态
            resetUserExpandedStates();
        }
        //省略根SCREEN_OFF无关的代码
        Trace.endSection();
    }
};

Summarize:

  1. During initialization, actively trigger SCREEN_OFF and reset some UI displays.

4.2 setupPresenter() function

In the start() function, an important function that initializes the presenter is also called, namely setupPresenter(). The source code is as follows:

private void setUpPresenter() {
    
    
    //ActivityLaunchAnimator用于打开Activity时触发动画
    mActivityLaunchAnimator = new ActivityLaunchAnimator(this, mContext);
    //NotificationAnimationProvider用于提供从通知中打开Activity时的动画
    mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
            mNotificationShadeWindowViewController,
            mStackScrollerController.getNotificationListContainer(),
            mHeadsUpManager
    );

    //创建一个StatusBarNotificationPresenter,它表示的是一种用于呈现(presenter)Notifications的抽象,可以通过它查询Notification的状态
    mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanelViewController,
            mHeadsUpManager, mNotificationShadeWindowView, mStackScrollerController,
            mDozeScrimController, mScrimController, mNotificationShadeWindowController,
            mDynamicPrivacyController, mKeyguardStateController,
            mKeyguardIndicationController,
            this /* statusBar */, mShadeController,
            mLockscreenShadeTransitionController, mCommandQueue, mInitController,
            mNotificationInterruptStateProvider);

    //传递必要的对象给NotificationShelf对象
    mNotificationShelfController.setOnActivatedListener(mPresenter);

    //传递必要对象
    mRemoteInputManager.getController().addCallback(mNotificationShadeWindowController);

    //NotificationActivityStarter用于处理从Notification中启动Activity
    mNotificationActivityStarter =
            mStatusBarNotificationActivityStarterBuilder
                    .setStatusBar(this)
                    .setActivityLaunchAnimator(mActivityLaunchAnimator)
                    .setNotificationAnimatorControllerProvider(mNotificationAnimationProvider)
                    .setNotificationPresenter(mPresenter)
                    .setNotificationPanelViewController(mNotificationPanelViewController)
                    .build();
    //为mStackScroller设置必要对象,mStackScroller对象即为Notification的父容器NotificationStackScrollLayout
    mStackScroller.setNotificationActivityStarter(mNotificationActivityStarter);

    //为NotificationGutsManager设置NotificationActivityStarter对象,NotificationGutsManager
    //是长按notification之后,出现的图标
    mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);

    //初始化NotificationController
    mNotificationsController.initialize(
            this,
            mBubblesOptional,
            mPresenter,
            mStackScrollerController.getNotificationListContainer(),
            mNotificationActivityStarter,
            mPresenter);
}

Judging from this function, it is mainly responsible for processing the following content:

  1. Initialize the object that opens the Activity from StatusBar
  2. Initialize the object that opens the Activity from Notification
  3. Initialize the object that opens the Activity from NotificationGuts

We have already handled the Notification-related initialization before. Next, we will initialize the keyguard-related initialization, which starts from the startKeyguard() function.

4.3 startKeyguard() function

The source code of the startKeygurad() function is as follows:

protected void startKeyguard() {
    
    
    Trace.beginSection("StatusBar#startKeyguard");
    //获取生物解锁控制器,它负责人脸,指纹解锁,虹膜等的解锁
    mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
    //监听生物解锁的各个模式事件,具体细节见后续文章的指纹解锁
    mBiometricUnlockController.setBiometricModeListener(
            new BiometricUnlockController.BiometricModeListener() {
    
    
                @Override
                public void onResetMode() {
    
    
                    setWakeAndUnlocking(false);
                }

                @Override
                public void onModeChanged(int mode) {
    
    
                    switch (mode) {
    
    
                        case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM:
                        case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING:
                        case BiometricUnlockController.MODE_WAKE_AND_UNLOCK:
                            setWakeAndUnlocking(true);
                    }
                }

                @Override
                public void notifyBiometricAuthModeChanged() {
    
    
                    StatusBar.this.notifyBiometricAuthModeChanged();
                }

                private void setWakeAndUnlocking(boolean wakeAndUnlocking) {
    
    
                    if (getNavigationBarView() != null) {
    
    
                        getNavigationBarView().setWakeAndUnlocking(wakeAndUnlocking);
                    }
                }
            });
    //将必要对象注册给StatusBarKeyguardViewManager对象
    mStatusBarKeyguardViewManager.registerStatusBar(
            /* statusBar= */ this, getBouncerContainer(),
            mNotificationPanelViewController, mBiometricUnlockController,
            mStackScroller, mKeyguardBypassController);
    //KeyguardIndicationController
    mKeyguardIndicationController
            .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
    mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
    mRemoteInputManager.getController().addCallback(mStatusBarKeyguardViewManager);
    //DynamicPrivacyController负责动态控制Notification内容的可见性
    mDynamicPrivacyController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);

    //LightBarController负责浅色模式如何应用到icon上 
    mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
    mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
    mKeyguardDismissUtil.setDismissHandler(this::executeWhenUnlocked);
    Trace.endSection();

    //注意如果上面没有注释的,可以直接搜索对象名,在前文中有相应注释
}

This function is also very simple. It constructs each object and then passes each object to the required object.

At this point, the entire StatusBar initialization process is completed. Next, we will make a summary of its key parts to grasp its main context.

  1. The system startup is completed, start system_server
  2. system_server starts SystemUIService
  3. SystemUIService starts SystemUIApplication's startServicesIfNeeded()
  4. startServicesIfNeeded() starts the StatusBar
    (the first four are the main contents of "Android 12 source code analysis - application layer two" and "Android 12 source code analysis - application layer three")
  5. In the start() function, establish a connection with system_server
  6. In the start() function, call createAndAddWindow() to create the required window
  7. In the start() function, initialize each required necessary object
  8. In the createAndAddWindow() function, call makeStatusBarView() to create each Window and View and add them to the screen.
  9. In the makeStatusBarView() function, call inflateStatusBarWindow() to create two windows, StatusBar and NotificationShade.
  10. In the makeStatusBarView() function, call createNavigationBar() to create the NavigationBar window
  11. In the makeStatusBarView() function, create a CollapsedStatusBarFragment used in the StatusBar window, which represents the specific content in the StatusBar.
  12. In the makeStatusBarView() function, create a QSFragment used in the NotificationShade window, which represents the content of the QS in the entire drop-down status bar.
  13. And during the initialization process, coordinate the relationship between various objects
  14. And during the initialization process, turn off the screen and restore the UI to an initial state

In this article, we did not discuss the creation of CollapsedStatusBarFragment in too much depth, but stayed on its top-level View. Therefore, the next few articles will introduce the creation process of CollapsedStatusBarFragment, QSFragment and StackScroll respectively, and finally Introduce the creation process of NavigationBar.

Next article, UI creation and initialization of StatusBar window

ps1: In the process of writing, I often find that Chinese and English are mixed, especially the names, which are sometimes quite confusing. If readers have any questions, they can leave a message and tell them everything they know.

ps2: Of course there are bound to be errors in the article, and I hope you can enlighten me.

Guess you like

Origin blog.csdn.net/xiaowanbiao123/article/details/132842129