Analyse du code source Android 12 - couche d'application cinq (processus de démarrage de la classe StatusBar de SystemUI et création de trois fenêtres)

Analyse du code source Android 12 - couche d'application cinq (processus de démarrage de la classe StatusBar de SystemUI et création de trois fenêtres)

Dans l'article précédent, nous avons présenté la présentation de base et les concepts de base de l'application SystemUI. Ensuite, nous entrons dans la manière dont chaque interface utilisateur de l'application SystemUI est ajoutée à l'écran. Commençons donc par la création de trois fenêtres.

Remarque : Trois fenêtres, à savoir la fenêtre StatusBar, la fenêtre NavigationBar et la fenêtre NotificationShade.

Ces trois fenêtres sont toutes créées à partir de StatusBar.java, nous allons donc commencer par cette classe.

Cet article doit être consulté conjointement avec le billet de blog précédent, qui est un aperçu général de l'ensemble de la mise en page. Cet article peut être considéré comme un aperçu de l’ensemble de la classe clé.

L'adresse du billet de blog précédent : "Analyse du code source Android 12 - Couche d'application quatre (conception de mise en page de base et concepts de base de 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.Configuration Dagger2 de StatusBar

Si vous lisez attentivement le code source de StatusBar, vous constaterez que le constructeur de StatusBar n'est pas marqué de l'annotation @Inject. Ensuite, la StatusBar ne sera pas automatiquement créée. Mais afin de mieux rejoindre le diagramme Dagger2, nous fournissons l'objet StatusBar via @Provides. comme suit:

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

A partir du code ci-dessus, nous pouvons obtenir : Le module StatusBarPhoneModule fournit une méthode pour créer une StatusBar. Autrement dit, lorsque SystemUI nécessite StatusBar, il sera fourni par la méthode provideStatusBar.

Dans le constructeur de StatusBar, il s'agit simplement d'une simple affectation d'objet, pas besoin d'entrer dans les détails. Quant aux abstractions logiques correspondant à ces objets, nous les mentionnerons plus en détail lors de leur utilisation.

Remarque : Pour une explication de @Provides et de la manière dont Dagger2 implémente provideStatusBar et StatusBarPhoneModule, voir « Analyse du code source Android 12 - Application Layer Three (SystemUIFactory et son analyse des dépendances) http://t.csdn.cn/1o4P3 »

Ensuite, StatusBarPhoneModule sera définitivement inclus dans SysUIComponent. Trions la relation entre eux.

Recherchez l’intégralité du code source de SystemUI et vous pouvez voir le code suivant :

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

Le module StatusBarModule est inclus dans le module SystemUIBinder, comme suit :

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

Le module SystemUIBinder est inclus par SystemUIComponent comme suit :

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

Résumons sa relation d’inclusion :

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

2.La première opportunité de créer StatusBar

Lorsque system_server démarre SystemUIService, il activera la fonction startServicesIfNeeded() de SystemUIApplication.

Dans cette fonction, le service correspondant sera démarré en fonction des paramètres de configuration. Parmi eux, StatusBar est dans la configuration. Une fois la configuration lue, le solveSystemUI de ContextComponentHelper est appelé pour demander si l'objet correspondant peut être fourni dans Dagger2. C'est l'époque où StatusBar a été fondé pour la première fois.

Pour le processus spécifique de cette partie, voir : "Analyse du code source Android 12 - Couche d'application 2 (organisation générale et processus de démarrage de SystemUI) http://t.csdn.cn/Gk418 " fonction startServicesIfNeeded()

Afin d'avoir une sensation intuitive, voici une image de la pile d'appels créée pour la première fois. comme suit

Insérer la description de l'image ici

Remarque : Pour plus de détails sur l'obtention de la pile d'appels, voir : "Analyse du code source Android 12 - Couche d'application 1 (préparation de l'interface système) http://t.csdn.cn/Frjah " (Il s'agit d'un article incontournable, assurez-vous maîtriser ses techniques et méthodes)

3. Initialisation de StatusBar

Après avoir été créées dans la fonction startServicesIfNeeded() de SystemUIApplication, les deux méthodes de SystemUI seront appelées immédiatement, et StatusBar hérite de SystemUI, donc ces deux méthodes seront également appelées :

  1. Appelez d’abord la méthode start()
  2. Appelez ensuite la méthode onBootCompleted()

En regardant la StatusBar, vous constaterez qu'elle ne remplace pas la méthode onBootCompleted(). Ensuite, l'initialisation de StatusBar n'aura que la méthode start()

4. Fonction StatusBar.start()

La fonction StatusBar.start() est particulièrement longue. Le code source est le suivant :

Remarque : Cet article se concentre sur son processus de démarrage et n'introduira pas trop de détails spécifiques sur chaque classe. Par exemple, il n'introduira pas la logique de conception détaillée de ScreenLifeCycle. Cette logique de conception détaillée sera présentée dans les chapitres après l'introduction de l'ensemble du processus de démarrage.

@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(/*省略代码*/}

La fonction start() remplit principalement les fonctions suivantes :

  1. Initialisez chaque classe métier liée à l'ensemble de l'application SystemUI
  2. Établir des relations de référence entre ces
  3. Initialisez la configuration dans StatusBarManagerService, telle que disablFlag, icône, barre transitoire, etc.
  4. Appelez createAndAddWindow() pour créer l'interface utilisateur requise

Ensuite, nous commençons par la fonction createAndAddWindow() et examinons le processus de création de l'interface utilisateur.

Supplément au concept de base

  1. heads up : une méthode d'affichage des notifications de SystemUI qui permet aux notifications importantes d'apparaître en haut de l'écran sous forme de cartes.
  2. Notification par bulle : la notification par bulle est une méthode d'affichage de notification qui flotte sur l'écran, comme le contenu du message texte reçu par Messages by Google.
  3. La relation entre StatusBar et StatusBarManagerService : En tant qu'application, SystemUI ne peut pas être utilisé par d'autres utilisateurs. Afin de garantir l'utilisation par d'autres utilisateurs, il existe un service StatusBarService à l'intérieur du système, qui se trouve dans le processus system_server. Il est responsable de interagir avec d'autres utilisateurs. En même temps, lorsque SystemUI sera démarré, il s'enregistrera dans le service StatusBarSerivce. De cette manière, le service StatusBarService peut appeler la fonction StatusBar dans SystemUI. La structure simple est la suivante : SystemUI<---->StatusBarManagerService<----->autre application. Afin de communiquer en douceur entre eux, la communication par classeur est utilisée.
  4. CommandQueue : Dans le troisième point, nous avons mentionné que StatusBarManagerService et SystemUI communiquent via Binder. Lorsque SystemUI souhaite appeler StatusBarManagerService, il utilise l'interface IStatusBarService. Lorsque StatusBarManagerService appelle SystemUI, il utilise l'interface IStatusBar. L'implémentation de cette interface côté SystemUI est CommandQueue.ComandQueue peut être compris comme : une file d'attente de commandes de l'extérieur (par rapport à l'extérieur de SystemUI).
  5. DemoMode : Mode démo. Le mode démo corrigera une fausse barre d'état, qui peut être utilisée pour déboguer l'interface utilisateur de chaque icône. Concernant les instructions supplémentaires d'ouverture et de fermeture de DemoMode, nous les mentionnerons en détail plus tard.
  6. DisableFlags : représente les fonctions qui doivent être désactivées dans SystemUI. Il est divisé en deux types, Disable1 et Disable2. Si d'autres processus doivent modifier les valeurs de ces deux, ils peuvent utiliser la fonction Disablexxx() de IStatusBarService. pour le modifier.
    • Les valeurs de Disable1 sont :
      • DISABLE_NONE : ne désactive rien
      • DISABLE_EXPAND : désactiver l'expansion de la liste déroulante
      • DISABLE_NOTIFICATION_ICONS : désactiver les icônes de notification
      • DISABLE_NOTIFICATION_ALERTS : désactivez les sons de notification, les vibrations, les alertes contextuelles et d'autres fonctions
      • DISABLE_NOTIFICATION_TICKER : désactiver la barre de défilement des notifications
      • DISABLE_SYSTEM_INFO : désactiver l'affichage des informations dans la zone centrale de la barre d'état
      • DISABLE_HOME/RECENT/BACK : désactivez respectivement les boutons d'accueil, récent et BACK dans la barre de navigation.
      • DISABLE_CLOCK : Désactiver l'affichage de l'horloge dans la barre d'état
      • DISABLE_SEARCH : désactiver la recherche
      • DISABLE_ONGOING_CALL_CHIP : Désactivez l'icône d'appel dans la barre d'état
    • Les valeurs de Disable2 sont :
      • DISABLE_NONE : ne désactive rien
      • DISABLE_QUICK_SETTINGS : désactiver QS
      • DISABLE_SYSTEM_ICON : désactiver l'icône du système
      • DISABLE_NOTIFICATION_SHADE : désactiver la fenêtre NotificationShade
      • DISABLE_GLOBAL_ACTION : désactivez GlobalActionDialog, c'est-à-dire activez et désactivez la boîte de dialogue contextuelle
      • DISABLE_ROTATE_SUGGESTIONS : désactiver les icônes de suggestion de rotation dans la barre de navigation
  7. Mode ambiant : le mode ambiant est lorsque l'écran est éteint et certaines images affichées sur l'écran sont intégrées à l'environnement environnant. Par exemple, le ciel étoilé de Van Gogh est affiché sur le téléviseur comme décoration pour tout le mur. Il est appelé : mode de fusion ambiante
    Insérer la description de l'image ici

4.1Fonction createAndAddWindwo()

Le texte original de la fonction createAndAddWindow() est le suivant :

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

Remarque : Pour obtenir des instructions sur NotificationShadeWindow et StatusBarWindow, consultez « Analyse du code source Android 12 – Couche d'application quatre (conception de mise en page de base et concepts de base de SystemUI) http://t.csdn.cn/ioWFS »

Ensuite, jetez un œil à la fonction makeStatusBarView()

4.1.1 Fonction makeStatusBarView()

La fonction makeStatusBarView() est responsable de la création des vues des trois fenêtres principales. Le code source est le suivant :

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));
}

Cette méthode remplit les fonctions suivantes :

  1. Initialiser diverses ressources
  2. Appelez inflateStatusBarWindow() pour construire le conteneur View de niveau supérieur de la fenêtre NotificationShade et de la fenêtre StaturBar.
  3. Appelez inflateShelf() pour construire NotificationShelf
  4. Appelez createNavigationBar() pour construire le conteneur View de niveau supérieur de la fenêtre NavigationBar
  5. Créez ensuite une vue réutilisable via Fragment et ajoutez-la à ces vues de conteneur de niveau supérieur, telles que QSFragment, CollapsedStatusBarFragment.
  6. Créez à nouveau la connexion entre le contrôleur et la vue
  7. Inscrivez-vous aux émissions qui vous intéressent

Supplément au concept de base

  1. AOD : toujours affiché, SystemUI fournit une UI qui s'affichera lorsque l'écran est éteint.
  2. QS : Paramètres rapides, qui est une rangée d'icônes qui peuvent être rapidement activées et désactivées après avoir abaissé la barre d'état.
  3. Wake lock : obtenez un objet WakeLock en appelant newWakeLock() de PowerManager. Pour verrouiller, appelez WakeLock.acquire(), pour libérer, appelez WakeLock.release(). WakeLock peut être configuré avec différents niveaux de verrouillage, notamment :
    • PARTIAL_WAKE_LOCK : le wakelock partiel, le rétroéclairage de l'écran et du clavier peuvent être désactivés, mais le processeur continuera à fonctionner jusqu'à ce que la version soit appelée.
    • FULL_WAKE_LOCK : verrouillage de réveil complet, le processeur est toujours en cours d'exécution et le rétroéclairage de l'écran et du clavier ne sera pas éteint.
    • SCREEN_DIM_WAKE_LOCK : verrouillage de réveil avec atténuation de l'écran, l'écran est toujours allumé, mais s'assombrit et le rétroéclairage du clavier peut être éteint. Appuyer sur le bouton d'alimentation libérera le verrouillage
    • SCREEN_BRIGHT_WAKE_LOCK : l'écran ne s'assombrit pas et le rétroéclairage du clavier peut être éteint. Si vous appuyez sur power, le verrou sera libéré

Nous introduisons ensuite deux fonctions utilisées pour créer des vues de niveau supérieur, inflateStatusBarWindow() et createNavigationBar().

4.1.1.1Fonction inflateStatusBarWindow()

Le code source de la fonction est le suivant :

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();
}

Dans cette fonction inflateStatusBarWindow(), le travail principal effectué est :

  1. Créez la vue de niveau supérieur et initialisez-la
  2. Établir la connexion entre le contrôleur et la vue

Voyons d'abord comment la fonction ci-dessus crée la vue de niveau supérieur de NotificationShadeWindow.

Le getNotificationShadeWindow() de SuperStatusBarViewFactory est le suivant

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;
}

Remarque : Pour une description détaillée du fichier super_notification_shade.xml, consultez « Analyse du code source Android 12 - Couche d'application quatre (conception de mise en page de base et concepts de base de SystemUI) http://t.csdn.cn/Jmtwu »

Ensuite, vous devez examiner comment la vue de niveau supérieur de la fenêtre StatusBar est créée. Le code source est le suivant :

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;
}

Résumé : méthode inflateStatusBarWindow(), utilisée pour créer la vue de niveau supérieur de deux fenêtres (StatusBar et NotificationShade)

Remarque : Cet article se concentre principalement sur le processus d'initialisation de la classe StatusBar. Les détails après chaque vue de niveau supérieur et les détails de la sous-vue correspondante seront présentés en détail dans les chapitres correspondants.

4.1.1.2 Fonction createNavigationBar()

Le code source de createNavigationBar() est le suivant :

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

Remarque : Le sujet de cet article est le processus de démarrage de StatusBar et la création initiale de trois fenêtres. Dans les articles suivants, nous discuterons en détail du processus de création de chaque fenêtre.

4.1.1.3 Déclencher activement ACTION_SCREEN_OFF pour la première fois

Dans la fonction makeStatusBarView(), la méthode onReceive du récepteur de diffusion est activement appelée et une intention de ACTION_SCREEN_OFF est transmise.

Nous regardons ensuite les opérations correspondant à cette 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();
    }
};

Résumer:

  1. Pendant l'initialisation, déclenchez activement SCREEN_OFF et réinitialisez certains affichages de l'interface utilisateur.

4.2 Fonction setupPresenter()

Dans la fonction start(), une fonction importante qui initialise le présentateur est également appelée, à savoir setupPresenter(). Le code source est le suivant :

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);
}

Au vu de cette fonction, il est principalement responsable du traitement des contenus suivants :

  1. Initialisez l'objet qui ouvre l'activité depuis StatusBar
  2. Initialisez l'objet qui ouvre l'activité à partir de la notification
  3. Initialisez l'objet qui ouvre l'activité depuis NotificationGuts

Nous avons déjà traité de l'initialisation liée aux notifications auparavant. Ensuite, nous initialiserons l'initialisation liée au keyguard, qui démarre à partir de la fonction startKeyguard().

4.3 Fonction startKeyguard()

Le code source de la fonction startKeygurad() est le suivant :

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();

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

Cette fonction est également très simple : elle construit chaque objet puis transmet chaque objet à l'objet requis.

À ce stade, l'ensemble du processus d'initialisation de StatusBar est terminé. Ensuite, nous ferons un résumé de ses éléments clés pour saisir son contexte principal.

  1. Le démarrage du système est terminé, démarrez system_server
  2. system_server démarre SystemUIService
  3. SystemUIService démarre startServicesIfNeeded() de SystemUIApplication
  4. startServicesIfNeeded() démarre la barre d'état
    (les quatre premiers sont le contenu principal de « Analyse du code source Android 12 – couche d'application deux » et « Analyse du code source Android 12 – couche d'application trois »).
  5. Dans la fonction start(), établissez une connexion avec system_server
  6. Dans la fonction start(), appelez createAndAddWindow() pour créer la fenêtre requise
  7. Dans la fonction start(), initialisez chaque objet nécessaire requis
  8. Dans la fonction createAndAddWindow(), appelez makeStatusBarView() pour créer chaque fenêtre et vue et les ajouter à l'écran.
  9. Dans la fonction makeStatusBarView(), appelez inflateStatusBarWindow() pour créer deux fenêtres, StatusBar et NotificationShade.
  10. Dans la fonction makeStatusBarView(), appelez createNavigationBar() pour créer la fenêtre NavigationBar
  11. Dans la fonction makeStatusBarView(), créez un CollapsedStatusBarFragment utilisé dans la fenêtre StatusBar, qui représente le contenu spécifique de StatusBar.
  12. Dans la fonction makeStatusBarView(), créez un QSFragment utilisé dans la fenêtre NotificationShade, qui représente le contenu du QS dans toute la barre d'état déroulante.
  13. Et pendant le processus d'initialisation, coordonnez la relation entre les différents objets
  14. Et pendant le processus d'initialisation, éteignez l'écran et restaurez l'interface utilisateur à son état initial.

Dans cet article, nous n'avons pas discuté de la création de CollapsedStatusBarFragment de manière trop approfondie, mais sommes restés sur sa vue de niveau supérieur. Par conséquent, les prochains articles présenteront respectivement le processus de création de CollapsedStatusBarFragment, QSFragment et StackScroll, et enfin présenteront la création processus de NavigationBar.

Article suivant, Création de l'UI et initialisation de la fenêtre StatusBar

ps1 : En cours d'écriture, je trouve souvent que le chinois et l'anglais se mélangent, notamment les noms qui prêtent parfois à confusion. Si les lecteurs ont des questions, ils peuvent laisser un message et leur dire tout ce qu'ils savent.

ps2 : Bien sur il y a forcément des erreurs dans l'article, et j'espère que vous pourrez m'éclairer.

Je suppose que tu aimes

Origine blog.csdn.net/xiaowanbiao123/article/details/132842129
conseillé
Classement