Android SystemUI之StatusBar,状态栏(二)

Android  SystemUI系列:

     1.Android  SystemUI之启动流程(一)

     2.Android SystemUI之StatusBar,状态栏(二)

     3.Android SystemUI之下拉菜单,通知栏,快捷面板(三)

     4.Android SystemUI之NavigationBar,导航栏(四)

     5.Android SystemUI之Recent,近期列表(五)

 

一、StatusBar简介

      systemui其实结构是比较复杂,里面管理各种服务,导航栏,状态栏,近期列表,下拉菜单,关机界面等,其中以导航栏和状态栏,近期列表用的比较多,也是本博文会重点讲解的内容。从结构上来讲下拉菜单和状态栏都是属于statusbar,结构树上也是属于顶层的super_status_bar.xml(StatusBarWindowView),说这么多还不如直接上图,这样大家看的比较清晰直观

Android SystemUI之StatusBar,状态栏(二)_第1张图片

从上图可以比较直观的看出来顶层树是super_status_bar,之后会走两个分支status_bar_container和status_bar_expanded,status_bar_container这个分支主要呈现的是状态栏界面,状态栏细分左边和右边,左边是通知栏,右边是系统功能的状态图标显示,status_bar_expanded这个分支主要呈现的下拉菜单界面,其实下拉菜单中又分快捷图标和短信通知栏,但是这些内容在后续的章节会详细说。本章博文主要讲解status_bar_container这个分支

二、StatusBar创建

   在前面的博文(Android SystemUI之启动流程)有讲过服务的其中mServices[i].start();StatusBar也是SystemUI的一个服务,所以它的启动入口也是从start()方法开始,包括后面的近期列表服务(Recents)。

 1.StatusBar  start

    public void start() {
    //主要是有关notification的服务类获取
        mGroupManager = Dependency.get(NotificationGroupManager.class);
        mVisualStabilityManager = Dependency.get(VisualStabilityManager.class);
        mNotificationLogger = Dependency.get(NotificationLogger.class);
        mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
        mNotificationListener =  Dependency.get(NotificationListener.class);//notification监听信息的service
        mGroupManager = Dependency.get(NotificationGroupManager.class);
        mNetworkController = Dependency.get(NetworkController.class);
        mUserSwitcherController = Dependency.get(UserSwitcherController.class);
        mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
        mScreenLifecycle.addObserver(mScreenObserver);
        mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
        mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
        mBatteryController = Dependency.get(BatteryController.class);//电池管理控制类。
        mAssistManager = Dependency.get(AssistManager.class);
        mOverlayManager = IOverlayManager.Stub.asInterface(
                ServiceManager.getService(Context.OVERLAY_SERVICE));
        mLockscreenUserManager = Dependency.get(NotificationLockscreenUserManager.class);
        mGutsManager = Dependency.get(NotificationGutsManager.class);
        mMediaManager = Dependency.get(NotificationMediaManager.class);
        mEntryManager = Dependency.get(NotificationEntryManager.class);//notification管理类,
        mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
        mAppOpsListener = Dependency.get(AppOpsListener.class);
        mAppOpsListener.setUpWithPresenter(this, mEntryManager);
        mZenController = Dependency.get(ZenModeController.class);
        mKeyguardViewMediator = getComponent(KeyguardViewMediator.class);

        mColorExtractor = Dependency.get(SysuiColorExtractor.class);
        mColorExtractor.addOnColorsChangedListener(this);

        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

        mDisplay = mWindowManager.getDefaultDisplay();
        updateDisplaySize();

        Resources res = mContext.getResources();
        mVibrateOnOpening = mContext.getResources().getBoolean(
                R.bool.config_vibrateOnIconAnimation);
        mVibratorHelper = Dependency.get(VibratorHelper.class);
        mScrimSrcModeEnabled = res.getBoolean(R.bool.config_status_bar_scrim_behind_use_src);
        mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);

        DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER));
        putComponent(StatusBar.class, this);

        // start old BaseStatusBar.start().
        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
        mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
                Context.DEVICE_POLICY_SERVICE);

        mAccessibilityManager = (AccessibilityManager)
                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);

        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);

        mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
     //StatusBarManagerService,这个服务端在framework中 :base\services\core\java\com\android\server\statusbar
        mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));

        mRecents = getComponent(Recents.class);//近期任务列表

        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
        mLockPatternUtils = new LockPatternUtils(mContext);//锁屏工具类。密码锁屏,滑动锁屏都会调用这个工具类来解锁。

        mMediaManager.setUpWithPresenter(this, mEntryManager);

        // Connect in to the status bar manager service
        //统筹systemui与mBarService数据交换,方法调用,app设置全屏显示隐藏任务栏,都是通过mCommandQueue来实现的。
        mCommandQueue = getComponent(CommandQueue.class);
        mCommandQueue.addCallbacks(this);


         /* switches[0] = gatherDisableActionsLocked(mCurrentUserId, 1);
            switches[1] = mSystemUiVisibility;
            switches[2] = mMenuVisible ? 1 : 0;
            switches[3] = mImeWindowVis;
            switches[4] = mImeBackDisposition;
            switches[5] = mShowImeSwitcher ? 1 : 0;
            switches[6] = gatherDisableActionsLocked(mCurrentUserId, 2);
            switches[7] = mFullscreenStackSysUiVisibility;
            switches[8] = mDockedStackSysUiVisibility;
            */
            //上面的参数都是通过CommandQueue.Callbacks里面的函数来设置的。因此在systemui初始化的时候都是空或者0
		
        int[] switches = new int[9];//一些禁用列表
        ArrayList binders = new ArrayList<>();
        ArrayList iconSlots = new ArrayList<>();//图标名称
        ArrayList icons = new ArrayList<>();//图标
        Rect fullscreenStackBounds = new Rect();
        Rect dockedStackBounds = new Rect();
        try {
			//mCommandQueue继承IStatusBar.Stub,mCommandQueue是IStatusBar的BN端,mBarService是BP端
			//向IStatusBarServie进行注册,并获取所有保存在IStatusBarService中的信息
            mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
                    fullscreenStackBounds, dockedStackBounds);
        } catch (RemoteException ex) {
            // If the system process isn't there we're doomed anyway.
        }
     
	  
        createAndAddWindows();
 
        // Make sure we always have the most current wallpaper info.
        IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
        mContext.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter);
        mWallpaperChangedReceiver.onReceive(mContext, null);

        mLockscreenUserManager.setUpWithPresenter(this, mEntryManager);
		//初始化switches 的值
        mCommandQueue.disable(switches[0], switches[6], false /* animate */);
		//systemui 颜色和可见性
        setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff,
                fullscreenStackBounds, dockedStackBounds);
        topAppWindowChanged(switches[2] != 0);
        // StatusBarManagerService has a back up of IME token and it's restored here.
        //输入法的值
        setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0);

        // Set up the initial icon state
        int N = iconSlots.size();
        for (int i=0; i < N; i++) {
            mCommandQueue.setIcon(iconSlots.get(i), icons.get(i));
        }

        // Set up the initial notification state.
        mNotificationListener.setUpWithPresenter(this, mEntryManager);

 
        if (DEBUG) {
            Log.d(TAG, String.format(
                    "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
                   icons.size(),
                   switches[0],
                   switches[1],
                   switches[2],
                   switches[3]
                   ));
        }

        setHeadsUpUser(mLockscreenUserManager.getCurrentUserId());

        IntentFilter internalFilter = new IntentFilter();
        internalFilter.addAction(BANNER_ACTION_CANCEL);
        internalFilter.addAction(BANNER_ACTION_SETUP);
        mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,
                null);
				
		//yuanqi add start
	    IntentFilter wifiStatefilter = new IntentFilter();
	    wifiStatefilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
	    mContext.registerReceiver(mWifiStateReceiver, wifiStatefilter);
	    //yuanqi add end
				
				

        IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
                Context.VR_SERVICE));
        try {
            vrManager.registerListener(mVrStateCallbacks);
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to register VR mode state listener: " + e);
        }

        IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
                ServiceManager.getService(Context.WALLPAPER_SERVICE));
        try {
            wallpaperManager.setInAmbientMode(false /* ambientMode */, false /* animated */);
        } catch (RemoteException e) {
            // Just pass, nothing critical.
        }

        // end old BaseStatusBar.start().

        // Lastly, call to the icon policy to install/update all the icons.
        //设置icon的图标策略类
        mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController);
		//设置icon的信号图标策略类
        mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController);

        mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
        mUnlockMethodCache.addListener(this);
		//开启锁屏的相关服务
        startKeyguard();

        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback);
        putComponent(DozeHost.class, mDozeServiceHost);

        mScreenPinningRequest = new ScreenPinningRequest(mContext);
        mFalsingManager = FalsingManager.getInstance(mContext);

        Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);

        Dependency.get(ConfigurationController.class).addCallback(this);
        observerProvision();
    }

上述代码比较长,也进一步验证了StatusBar在整个SystemUI的重要性

主要做了以下几件事:

    1.获取各种服务为后续工作做准备。

   2.建立farmework的联系,把自己注册到StatusBarService中以供其他app使用,这也就是为什么我们能在APP层来控制导航栏和状态栏可见的关键

 mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE));

  mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders, fullscreenStackBounds, dockedStackBounds);

  3. 创建StatusBar :createAndAddWindows() ,并且做一些初始化值。

   2.createAndAddWindows

 public void createAndAddWindows() {
        addStatusBarWindow();
    }

    private void addStatusBarWindow() {
        makeStatusBarView();
        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
        mRemoteInputManager.setUpWithPresenter(this, mEntryManager, this,
                new RemoteInputController.Delegate() {
                    public void setRemoteInputActive(NotificationData.Entry entry,
                            boolean remoteInputActive) {
                        mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive);
                        entry.row.notifyHeightChanged(true /* needsAnimation */);
                        updateFooter();
                    }
                    public void lockScrollTo(NotificationData.Entry entry) {
                        mStackScroller.lockScrollTo(entry.row);
                    }
                    public void requestDisallowLongPressAndDismiss() {
                        mStackScroller.requestDisallowLongPress();
                        mStackScroller.requestDisallowDismiss();
                    }
                });
        mRemoteInputManager.getController().addCallback(mStatusBarWindowManager);
        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());//把状态栏添加到window上面。
    }

createAndAddWindows其实没有做什么事,只是调用了addStatusBarWindow,而addStatusBarWindow又调用了makeStatusBarView,所以我们猜测makeStatusBarView是做具体事情的方法

3.makeStatusBarView

 //创建状态栏
    protected void makeStatusBarView() {
      //1.初始化资源文件:导航栏高度 状态栏高度 通知面板位置和高度等
        final Context context = mContext;
        updateDisplaySize(); // populates mDisplayMetrics
        updateResources();
        updateTheme();
      //加载layout文件super_status_bar,mStatusBarWindow
        inflateStatusBarWindow(context);
	  if(StatusBar.SYSTEMUI_START_DEBUG)Log.i(StatusBar.TAG_XIAO," makeStatusBarView  mStatusBarWindow getWidth"+mStatusBarWindow.getWidth()
	  	+",getHeight:"+mStatusBarWindow.getHeight());
	  
        mStatusBarWindow.setService(this);
        mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener());//设置触摸监听,如果子类没有销毁touch,父类使用
		

        // TODO: Deal with the ugliness that comes from having some of the statusbar broken out
        // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
        mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);//下拉菜单面板
        mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);//下拉通知信息滚动栏
        mZenController.addCallback(this);
        mActivityLaunchAnimator = new ActivityLaunchAnimator(mStatusBarWindow,
                this,
                mNotificationPanel,
                mStackScroller);
        mGutsManager.setUpWithPresenter(this, mEntryManager, mStackScroller, mCheckSaveListener,
                key -> {
                    try {
                        mBarService.onNotificationSettingsViewed(key);
                    } catch (RemoteException e) {
                        // if we're here we're dead
                    }
                });
        mNotificationLogger.setUpWithEntryManager(mEntryManager, mStackScroller);
        mNotificationPanel.setStatusBar(this);
        mNotificationPanel.setGroupManager(mGroupManager);
        mAboveShelfObserver = new AboveShelfObserver(mStackScroller);
        mAboveShelfObserver.setListener(mStatusBarWindow.findViewById(
                R.id.notification_container_parent));
        mKeyguardStatusBar = mStatusBarWindow.findViewById(R.id.keyguard_header);//锁屏界面显示

        mNotificationIconAreaController = SystemUIFactory.getInstance()//短信icon控制类
                .createNotificationIconAreaController(context, this);
        inflateShelf();
        mNotificationIconAreaController.setupShelf(mNotificationShelf);
        Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
        FragmentHostManager.get(mStatusBarWindow)
                .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
           if(StatusBar.SYSTEMUI_START_DEBUG)Log.i(StatusBar.TAG_XIAO,"makeStatusBarView addTagListener fragment:"+fragment+",tag:"+tag);     
                    CollapsedStatusBarFragment statusBarFragment =
                            (CollapsedStatusBarFragment) fragment;
                    statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);//加载短信通知的icon
                    mStatusBarView = (PhoneStatusBarView) fragment.getView();
                    mStatusBarView.setBar(this);
                    mStatusBarView.setPanel(mNotificationPanel);
                    mStatusBarView.setScrimController(mScrimController);
                    mStatusBarView.setBouncerShowing(mBouncerShowing);
                    if (mHeadsUpAppearanceController != null) {
                        // This view is being recreated, let's destroy the old one
                        mHeadsUpAppearanceController.destroy();
                    }
                    mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                            mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow);
                    setAreThereNotifications();
                    checkBarModes();
                    /// M: add for plmn display feature @{
                    attachPlmnPlugin();
                    ///@}
                }).getFragmentManager()
                .beginTransaction()
                .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                        CollapsedStatusBarFragment.TAG)
                .commit();
        mIconController = Dependency.get(StatusBarIconController.class);

        mHeadsUpManager = new HeadsUpManagerPhone(context, mStatusBarWindow, mGroupManager, this,
                mVisualStabilityManager);
        Dependency.get(ConfigurationController.class).addCallback(mHeadsUpManager);
        mHeadsUpManager.addListener(this);
        mHeadsUpManager.addListener(mNotificationPanel);
        mHeadsUpManager.addListener(mGroupManager);
        mHeadsUpManager.addListener(mVisualStabilityManager);
        mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
        mGroupManager.setHeadsUpManager(mHeadsUpManager);
        putComponent(HeadsUpManager.class, mHeadsUpManager);

        mEntryManager.setUpWithPresenter(this, mStackScroller, this, mHeadsUpManager);
        mViewHierarchyManager.setUpWithPresenter(this, mEntryManager, mStackScroller);

        if (MULTIUSER_DEBUG) {
            mNotificationPanelDebugText = mNotificationPanel.findViewById(R.id.header_debug_info);
            mNotificationPanelDebugText.setVisibility(View.VISIBLE);
        }

        try {
			//创建导航栏
            boolean showNav = mWindowManagerService.hasNavigationBar();
            if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
            if (showNav) {
                createNavigationBar();
            }
        } catch (RemoteException ex) {
            // no window manager? good luck with that
        }
        mScreenPinningNotify = new ScreenPinningNotify(mContext);
        mStackScroller.setLongPressListener(mEntryManager.getNotificationLongClicker());
        mStackScroller.setStatusBar(this);
        mStackScroller.setGroupManager(mGroupManager);
        mStackScroller.setHeadsUpManager(mHeadsUpManager);
        mGroupManager.setOnGroupChangeListener(mStackScroller);
        mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller);

        inflateEmptyShadeView();
        inflateFooterView();

        mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop);//paint绘制模式
        mBackdropFront = mBackdrop.findViewById(R.id.backdrop_front);
        mBackdropBack = mBackdrop.findViewById(R.id.backdrop_back);

        if (ENABLE_LOCKSCREEN_WALLPAPER) {
            mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
        }
     //layout :keyguard_bottom_area
        mKeyguardIndicationController =
                SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
                        mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
                        mNotificationPanel.getLockIcon());
        mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController);


        mAmbientIndicationContainer = mStatusBarWindow.findViewById(
                R.id.ambient_indication_container);

        // set the initial view visibility
        setAreThereNotifications();

        // TODO: Find better place for this callback.
        mBatteryController.addCallback(new BatteryStateChangeCallback() {
            @Override
            public void onPowerSaveChanged(boolean isPowerSave) {
                mHandler.post(mCheckBarModes);
                if (mDozeServiceHost != null) {
                    mDozeServiceHost.firePowerSaveChanged(isPowerSave);
                }
            }

            @Override
            public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
                // noop
            }
        });

        mLightBarController = Dependency.get(LightBarController.class);
        if (mNavigationBar != null) {
            mNavigationBar.setLightBarController(mLightBarController);
        }

        ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind);
        ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front);
        mScrimController = SystemUIFactory.getInstance().createScrimController(
                scrimBehind, scrimInFront, mLockscreenWallpaper,
                (state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color),
                scrimsVisible -> {
                    if (mStatusBarWindowManager != null) {
                        mStatusBarWindowManager.setScrimsVisibility(scrimsVisible);
                    }
                }, DozeParameters.getInstance(mContext),
                mContext.getSystemService(AlarmManager.class));
        if (mScrimSrcModeEnabled) {
            Runnable runnable = () -> {
                boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE;
                mScrimController.setDrawBehindAsSrc(asSrc);
                mStackScroller.setDrawBackgroundAsSrc(asSrc);
            };
            mBackdrop.setOnVisibilityChangedRunnable(runnable);
            runnable.run();
        }
        mStackScroller.setScrimController(mScrimController);
        mDozeScrimController = new DozeScrimController(mScrimController, context,
                DozeParameters.getInstance(context));

        // Other icons
        mVolumeComponent = getComponent(VolumeComponent.class);

        /// M: Support "Operator plugin - Customize Carrier Label for PLMN" @{
        SIMHelper.setContext(context);
        mStatusBarPlmnPlugin = OpSystemUICustomizationFactoryBase.getOpFactory(context)
                .makeStatusBarPlmn(context);
        if (supportCustomizeCarrierLabel()) {
            mCustomizeCarrierLabel = mStatusBarPlmnPlugin.customizeCarrierLabel(
                    mNotificationPanel, null);
        }
        /// M: Support "Operator plugin - Customize Carrier Label for PLMN" @}

        mNotificationPanel.setUserSetupComplete(mUserSetup);
        if (UserManager.get(mContext).isUserSwitcherEnabled()) {
            createUserSwitcher();
        }

        // Set up the quick settings tile panel
        //面板
        View container = mStatusBarWindow.findViewById(R.id.qs_frame);
        if (container != null) {
            FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
            ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
                    Dependency.get(ExtensionController.class)
                            .newExtension(QS.class)
                            .withPlugin(QS.class)
                            .withFeature(PackageManager.FEATURE_AUTOMOTIVE, CarQSFragment::new)
                            .withDefault(QSFragment::new)
                            .build());
            final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,
                    mIconController);
            mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow,
                    (visible) -> {
                        mBrightnessMirrorVisible = visible;
                        updateScrimController();
                    });
            fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
                QS qs = (QS) f;
                if (qs instanceof QSFragment) {
                    ((QSFragment) qs).setHost(qsh);
                    mQSPanel = ((QSFragment) qs).getQsPanel();
                    mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
                    mKeyguardStatusBar.setQSPanel(mQSPanel);
                }
            });
        }

        mReportRejectedTouch = mStatusBarWindow.findViewById(R.id.report_rejected_touch);
        if (mReportRejectedTouch != null) {
            updateReportRejectedTouchVisibility();
            mReportRejectedTouch.setOnClickListener(v -> {
                Uri session = mFalsingManager.reportRejectedTouch();
                if (session == null) { return; }

                StringWriter message = new StringWriter();
                message.write("Build info: ");
                message.write(SystemProperties.get("ro.build.description"));
                message.write("\nSerial number: ");
                message.write(SystemProperties.get("ro.serialno"));
                message.write("\n");

                PrintWriter falsingPw = new PrintWriter(message);
                FalsingLog.dump(falsingPw);
                falsingPw.flush();

                startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND)
                                .setType("*/*")
                                .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report")
                                .putExtra(Intent.EXTRA_STREAM, session)
                                .putExtra(Intent.EXTRA_TEXT, message.toString()),
                        "Share rejected touch report")
                                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
                        true /* onlyProvisioned */, true /* dismissShade */);
            });
        }

        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        if (!pm.isScreenOn()) {
            mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
        }
        mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
                "GestureWakeLock");
        mVibrator = mContext.getSystemService(Vibrator.class);
        int[] pattern = mContext.getResources().getIntArray(
                R.array.config_cameraLaunchGestureVibePattern);
        mCameraLaunchGestureVibePattern = new long[pattern.length];
        for (int i = 0; i < pattern.length; i++) {
            mCameraLaunchGestureVibePattern[i] = pattern[i];
        }

        // receive broadcasts
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG);
        context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);

        IntentFilter demoFilter = new IntentFilter();
        if (DEBUG_MEDIA_FAKE_ARTWORK) {
            demoFilter.addAction(ACTION_FAKE_ARTWORK);
        }
        demoFilter.addAction(ACTION_DEMO);
        context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
                android.Manifest.permission.DUMP, null);

        // listen for USER_SETUP_COMPLETE setting (per-user)
        mDeviceProvisionedController.addCallback(mUserSetupObserver);
        mUserSetupObserver.onUserSetupChanged();

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

上述代码块比较长,里面所包含的信息也比较多,除了状态栏的创建还有下拉菜单的创建。我们现在先讲状态栏的创建。

 1.初始化资源文件,获取状态栏高度,加载statusbar设备树super_status_bar :inflateStatusBarWindow(context),这个设备树的根View是StatusBarWindowView,StatusBarWindowView继承FrameLayout。

2.添加CollapsedStatusBarFragment,这个CollapsedStatusBarFragment就是作为加载状态栏的Fragment

 FragmentHostManager.get(mStatusBarWindow)
                .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {      
                    CollapsedStatusBarFragment statusBarFragment =
                            (CollapsedStatusBarFragment) fragment;
                    statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);//加载短信通知的icon
                    mStatusBarView = (PhoneStatusBarView) fragment.getView();
                    mStatusBarView.setBar(this);
                    mStatusBarView.setPanel(mNotificationPanel);
                    mStatusBarView.setScrimController(mScrimController);
                    mStatusBarView.setBouncerShowing(mBouncerShowing);
                    if (mHeadsUpAppearanceController != null) {
                        // This view is being recreated, let's destroy the old one
                        mHeadsUpAppearanceController.destroy();
                    }
                    mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                            mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow);
                    setAreThereNotifications();
                    checkBarModes();
                    /// M: add for plmn display feature @{
                    attachPlmnPlugin();
                    ///@}
                }).getFragmentManager()
                .beginTransaction()
                .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                        CollapsedStatusBarFragment.TAG)
                .commit();

4.CollapsedStatusBarFragment

     到CollapsedStatusBarFragment才算状态栏的开始,那么我们思考一下,状态图标是是怎样被加载到状态栏上,数据又如何获取的,搞明白这两个问题,状态栏的流程基本也就清楚了

我们先来看看CollapsedStatusBarFragment做了什么东西。熟悉Fragment的都清楚Fragment的加载流程onCreateView会加载layout,因此我们在oncreate中找到如下代码

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.status_bar, container, false);
    }

 

status_bar.xml的文件



    

    
        
        

            

            
            
                

                

            
        

        
        

        

            
        
    

    


上面的layout还是蛮多内容,但是我们只看三点:

1.根View :StatusBarWindowView,这个是一个继承FrameLayout的View。所以能比较初步的知道这个子View的界面的加载流程

2.@+id/status_bar_contents 这个LinearLayout,里面包含了@+id/status_bar_left_side  ,从名字来看就知道是状态栏左边部分。这个状态栏左边部分包含了时钟@+id/clock和短信通知@+id/notification_icon_area,这个我们在开始的是有说过。

3.@+id/system_icon_area这个也是一个LinearLayout包含了@layout/system_icons,这部分就是状态栏右边部分,里面包含了电池图标和系统状态图标



    

    

   从上面的代码我们能猜测出来,不管是系统状态图标还是短信通知图标都是动态加载,那我们就需要了解它是如何加载的,数据是如何获取的?

 

5.@+id/notification_icon_area 左边短信通知的添加流程

我们先来看看短信通知是的view结构加载过程。

 public void initNotificationIconArea(NotificationIconAreaController
            notificationIconAreaController) {
        ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);//短信通知icon
        mNotificationIconAreaInner =
                notificationIconAreaController.getNotificationInnerAreaView();
		//移除自己,再添加自己
        if (mNotificationIconAreaInner.getParent() != null) {
            ((ViewGroup) mNotificationIconAreaInner.getParent())
                    .removeView(mNotificationIconAreaInner);
        }
        notificationIconArea.addView(mNotificationIconAreaInner);
        // Default to showing until we know otherwise.
        showNotificationIconArea(false);
    }

如果熟悉View的添加流程很容易看懂上面代码的含义,先移除notificationIconArea上面的子view,然后再添加mNotificationIconAreaInner。

我们需要搞清的是NotificationIconAreaController这个类是做什么的?

   mNotificationIconAreaInner又是一个什么样的view?以及initNotificationIconArea这个方法在哪里被调用。

initNotificationIconArea是在StatusBar中添加CollapsedStatusBarFragment 中被调用:statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);

NotificationIconAreaController:这个类主要是用于短信icon的控制类。

mNotificationIconAreaInner是通过加载notification_icon_area而生成的view如下代码:

protected View inflateIconArea(LayoutInflater inflater) {
        return inflater.inflate(R.layout.notification_icon_area, null);
    }

layout.notification_icon_area 如下代码


    

看到这边好像我们还没看到短信icon被添加的具体代码,先不急,我们先看看数据是如何获取的。

NotificationListener这个类监听notification,至于为什么这个类能监听到短信变化。是因为它继承了NotificationListenerService

每次系统短信变化的时候会回调onNotificationPosted

  public void onNotificationPosted(final StatusBarNotification sbn,
            final RankingMap rankingMap) {
        if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);	
        if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) {
            mPresenter.getHandler().post(() -> {
                processForRemoteInput(sbn.getNotification(), mContext);
                String key = sbn.getKey();
                mEntryManager.removeKeyKeptForRemoteInput(key);
                boolean isUpdate =
                        mEntryManager.getNotificationData().get(key) != null;
                // In case we don't allow child notifications, we ignore children of
                // notifications that have a summary, since` we're not going to show them
                // anyway. This is true also when the summary is canceled,
                // because children are automatically canceled by NoMan in that case.
                if (!ENABLE_CHILD_NOTIFICATIONS
                        && mPresenter.getGroupManager().isChildInGroupWithSummary(sbn)) {
                    if (DEBUG) {
                        Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
                    }

                    // Remove existing notification to avoid stale data.
                    if (isUpdate) {
                        if (DEBUG) Log.d(TAG, "onNotificationPosted, removeNotification: " + sbn);
                        mEntryManager.removeNotification(key, rankingMap);
                    } else {
                        if (DEBUG) Log.d(TAG, "onNotificationPosted, updateRanking: " + sbn);
                        mEntryManager.getNotificationData()
                                .updateRanking(rankingMap);
                    }
                    return;
                }
							
                if (isUpdate) {
                    mEntryManager.updateNotification(sbn, rankingMap);
                } else {
                    mEntryManager.addNotification(sbn, rankingMap);
                }
            });
        }
    }

短信icon第一次添加都systemui会走NotificationEntryManager.addNotification

 public void addNotification(StatusBarNotification notification,
            NotificationListenerService.RankingMap ranking) {
        try {			
            addNotificationInternal(notification, ranking);
			
        } catch (InflationException e) {
            handleInflationException(notification, e);
        }
    }
  private void addNotificationInternal(StatusBarNotification notification,
            NotificationListenerService.RankingMap ranking) throws InflationException {
        String key = notification.getKey();
        if (CHATTY) Log.d(TAG, "addNotification key=" + key);

        mNotificationData.updateRanking(ranking);
 if(StatusBar.SYSTEMUI_START_DEBUG)Log.i(StatusBar.TAG_XIAO,"NotificationEntryManager addNotificationInternal   StatusBarNotification:"+ notification.toString());			
        NotificationData.Entry shadeEntry = createNotificationViews(notification);
        boolean isHeadsUped = shouldPeek(shadeEntry);
        if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
            if (shouldSuppressFullScreenIntent(shadeEntry)) {
                if (CHATTY) {
                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + key);
                }
            } else if (mNotificationData.getImportance(key)
                    < NotificationManager.IMPORTANCE_HIGH) {
                if (CHATTY) {
                    Log.d(TAG, "No Fullscreen intent: not important enough: "
                            + key);
                }
            } else {
                // Stop screensaver if the notification has a fullscreen intent.
                // (like an incoming phone call)
                SystemServicesProxy.getInstance(mContext).awakenDreamsAsync();

                // not immersive & a fullscreen alert should be shown
                if (CHATTY)
                    Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
                try {
                    EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
                            key);
                    notification.getNotification().fullScreenIntent.send();
                    shadeEntry.notifyFullScreenIntentLaunched();
                    mMetricsLogger.count("note_fullscreen", 1);
                } catch (PendingIntent.CanceledException e) {
                }
            }
        }
        abortExistingInflation(key);

        mForegroundServiceController.addNotification(notification,
                mNotificationData.getImportance(key));

        mPendingNotifications.put(key, shadeEntry);
        mGroupManager.onPendingEntryAdded(shadeEntry);
    }
 protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn)
            throws InflationException {
        if (CHATTY) {
            Log.d(TAG, "createNotificationViews(notification=" + sbn);
        }
 	
        NotificationData.Entry entry = new NotificationData.Entry(sbn);
        Dependency.get(LeakDetector.class).trackInstance(entry);
        entry.createIcons(mContext, sbn);
        // Construct the expanded view.
        //创建下来短信通知信息
        inflateViews(entry, mListContainer.getViewParentForNotification(entry));
        return entry;
    }

 从上面的三个方法来看主要工作是:1.StatusBarNotification 里面的信息转换成NotificationData.Entry,并且创建通知icon的显示View。这个View是StatusBarIconView继承imageView。

                                                          2.绑定一些监听,比如移除监听。

                                                          3.把新添加的信息保持在mPendingNotifications,这个集合保持了所有显示的通知icon

 

NotificationEntryManager.updateNotification

  public void updateNotification(StatusBarNotification notification,
            NotificationListenerService.RankingMap ranking) {
        try {
            updateNotificationInternal(notification, ranking);
        } catch (InflationException e) {
            handleInflationException(notification, e);
        }
    }

 updateNotificationInternal里面内容很多,我们就不细看,看跟View显示有关的内容:updateNotifications

  public void updateNotifications() {
        mNotificationData.filterAndSort();

        mPresenter.updateNotificationViews();
    }

mPresenter是NotificationPresenter的实例,NotificationPresenter是一个接口,那边我们就需要找到它的实现类是在哪里,它的实现类是StatusBar。

StatusBar.updateNotificationViews

 public void updateNotificationViews() {
        // The function updateRowStates depends on both of these being non-null, so check them here.
        // We may be called before they are set from DeviceProvisionedController's callback.
        if (mStackScroller == null || mScrimController == null) return;

        // Do not modify the notifications during collapse.
        if (isCollapsing()) {
            addPostCollapseAction(this::updateNotificationViews);
            return;
        }

        mViewHierarchyManager.updateNotificationViews();

        updateSpeedBumpIndex();
        updateFooter();
        updateEmptyShadeView();

        updateQsExpansionEnabled();

        // Let's also update the icons
        mNotificationIconAreaController.updateNotificationIcons();
    }

mNotificationIconAreaController这个实例就是我们前面介绍的icon的管理了。

NotificationIconAreaController.updateNotificationIcons

 public void updateNotificationIcons() {

        updateStatusBarIcons();
        updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
                NotificationShelf.SHOW_AMBIENT_ICONS, false /* hideDismissed */,
                false /* hideRepliedMessages */);

        applyNotificationIconsTint();
    }
public void updateStatusBarIcons() {
        updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
                false /* showAmbient */, true /* hideDismissed */, true /* hideRepliedMessages */);
    }
  private void updateIconsForLayout(Function function,
            NotificationIconContainer hostLayout, boolean showAmbient, boolean hideDismissed,
            boolean hideRepliedMessages) {
        ArrayList toShow = new ArrayList<>(
                mNotificationScrollLayout.getChildCount());
		//if(StatusBar.SYSTEMUI_START_DEBUG)Log.i(StatusBar.TAG_XIAO,"NotificationIconAreaController updateIconsForLayout hostLayout.getChildCount():"+hostLayout.getChildCount()+", mNotificationScrollLayout.getChildCount():"+ mNotificationScrollLayout.getChildCount());

        // Filter out ambient notifications and notification children.
        for (int i = 0; i < mNotificationScrollLayout.getChildCount(); i++) {
            View view = mNotificationScrollLayout.getChildAt(i);
            if (view instanceof ExpandableNotificationRow) {
                NotificationData.Entry ent = ((ExpandableNotificationRow) view).getEntry();
			//	if(StatusBar.SYSTEMUI_START_DEBUG)Log.i(StatusBar.TAG_XIAO,"NotificationIconAreaController updateIconsForLayout ent key:"+ent.key+" notification:"+ent.notification);
                if (shouldShowNotificationIcon(ent, showAmbient, hideDismissed,
                        hideRepliedMessages)) {
                    toShow.add(function.apply(ent));
                }
            }
        }

        // In case we are changing the suppression of a group, the replacement shouldn't flicker
        // and it should just be replaced instead. We therefore look for notifications that were
        // just replaced by the child or vice-versa to suppress this.

        ArrayMap> replacingIcons = new ArrayMap<>();
        ArrayList toRemove = new ArrayList<>();
		
        for (int i = 0; i < hostLayout.getChildCount(); i++) {
            View child = hostLayout.getChildAt(i);
            if (!(child instanceof StatusBarIconView)) {
                continue;
            }
            if (!toShow.contains(child)) {
                boolean iconWasReplaced = false;
                StatusBarIconView removedIcon = (StatusBarIconView) child;
                String removedGroupKey = removedIcon.getNotification().getGroupKey();
                for (int j = 0; j < toShow.size(); j++) {
                    StatusBarIconView candidate = toShow.get(j);
                    if (candidate.getSourceIcon().sameAs((removedIcon.getSourceIcon()))
                            && candidate.getNotification().getGroupKey().equals(removedGroupKey)) {
                        if (!iconWasReplaced) {
                            iconWasReplaced = true;
                        } else {
                            iconWasReplaced = false;
                            break;
                        }
                    }
                }
                if (iconWasReplaced) {
                    ArrayList statusBarIcons = replacingIcons.get(removedGroupKey);
                    if (statusBarIcons == null) {
                        statusBarIcons = new ArrayList<>();
                        replacingIcons.put(removedGroupKey, statusBarIcons);
                    }
                    statusBarIcons.add(removedIcon.getStatusBarIcon());
                }
                toRemove.add(removedIcon);
            }
        }
        // removing all duplicates
        ArrayList duplicates = new ArrayList<>();
        for (String key : replacingIcons.keySet()) {
            ArrayList statusBarIcons = replacingIcons.get(key);
            if (statusBarIcons.size() != 1) {
                duplicates.add(key);
            }
        }
        replacingIcons.removeAll(duplicates);
        hostLayout.setReplacingIcons(replacingIcons);

        final int toRemoveCount = toRemove.size();
        for (int i = 0; i < toRemoveCount; i++) {
            hostLayout.removeView(toRemove.get(i));
        }

        final FrameLayout.LayoutParams params = generateIconLayoutParams();
        for (int i = 0; i < toShow.size(); i++) {
            StatusBarIconView v = toShow.get(i);
            // The view might still be transiently added if it was just removed and added again
            hostLayout.removeTransientView(v);
            if (v.getParent() == null) {
                if (hideDismissed) {
                    v.setOnDismissListener(mUpdateStatusBarIcons);
                }
                hostLayout.addView(v, i, params);
            }
        }

        hostLayout.setChangingViewPositions(true);
        // Re-sort notification icons
        final int childCount = hostLayout.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View actual = hostLayout.getChildAt(i);
            StatusBarIconView expected = toShow.get(i);
            if (actual == expected) {
                continue;
            }
            hostLayout.removeView(expected);
            hostLayout.addView(expected, i);
        }
        hostLayout.setChangingViewPositions(false);
        hostLayout.setReplacingIcons(null);
    }

  从上面的代码不难看出updateIconsForLayout含税会把StatusBarIconView添加到NotificationIconContainer这个ViewGroup中,而NotificationIconContainer依据前面的分析是挂载在左边短信通知区域。到现在整个的通知信息加载流程算梳理完成。

 

6.@+id/system_icon_area系统icon的加载

  CollapsedStatusBarFragment.onViewCreated

 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mStatusBar = (PhoneStatusBarView) view;
        if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
            mStatusBar.go(savedInstanceState.getInt(EXTRA_PANEL_STATE));
        }
		//layout:system_icons  view:StatusIconContainer 是LinearLayout
		//DarkIconManager是一个对icon管理类。管理StatusBarIconView
        mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
        mDarkIconManager.setShouldLog(true);
        Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
        mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);//系统icon父类LinearLayout
        mClockView = mStatusBar.findViewById(R.id.clock);//时间icon
        showSystemIconArea(false);
        showClock(false);
        initEmergencyCryptkeeperText();
        initOperatorName();
    }

上述代码中我们需要比较关注的代码是:

mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons))

Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);

R.id.statusIcons这个其实是在system_icons.xml里面的StatusIconContainer,这个View是一个LinearLayout。

DarkIconManager是StatusBarIconController的一个内部类,DarkIconManager extends IconManager。IconManager这个类里面做的事情是创建StatusBarIconView,部分代码如下

  protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked,
                StatusBarIconHolder holder) {
            switch (holder.getType()) {
                case TYPE_ICON:
                    return addIcon(index, slot, blocked, holder.getIcon());

                case TYPE_WIFI:
                    return addSignalIcon(index, slot, holder.getWifiState());

                case TYPE_MOBILE:
                    return addMobileIcon(index, slot, holder.getMobileState());
            }

            return null;
        }

        @VisibleForTesting
        protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
                StatusBarIcon icon) {
            StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
            view.set(icon);
            mGroup.addView(view, index, onCreateLayoutParams());
            return view;
        }

上述代码来看也只是把StatusIconContainer保存到IconManager里面,到时候把子View的添加到StatusIconContainer。

是什么时候把子view添加到StatusIconContainer呢?

在StatusBar中有这两行代码

  mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController);
        //设置icon的信号图标策略类
    mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController);

从名字我们大概能猜到PhoneStatusBarPolicy是除了信号的状态Icon的所有系统Icon。而信号的icon就由StatusBarSignalPolicy来做初始化添加。

PhoneStatusBarPolicy

  //eMBMS status
        mIconController.setIcon(mSlotEmbms, R.drawable.stat_sys_embms, null);
        mIconController.setIconVisibility(mSlotEmbms, false);


        // Alarm clock
        mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
        mIconController.setIconVisibility(mSlotAlarmClock, false);

        // zen
        mIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null);
        mIconController.setIconVisibility(mSlotZen, false);

        // volume
        mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null);
        mIconController.setIconVisibility(mSlotVolume, false);
        updateVolumeZen();

        // cast
        mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);
        mIconController.setIconVisibility(mSlotCast, false);

        // hotspot
        mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
                mContext.getString(R.string.accessibility_status_bar_hotspot));
        mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());

        // managed profile
        mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
                mContext.getString(R.string.accessibility_managed_profile));
        mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible);

        // data saver
        mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
                context.getString(R.string.accessibility_data_saver_on));
        mIconController.setIconVisibility(mSlotDataSaver, false);

StatusBarIconControllerImpl

 public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
    
        int index = getSlotIndex(slot);
        StatusBarIconHolder holder = getIcon(index, 0);
	if(StatusBar.SYSTEMUI_START_DEBUG)Log.i(StatusBar.TAG_XIAO,"StatusBarIconControllerImpl setIcon slot:"+slot+",index:"+index+",holder:"+holder);	
        if (holder == null) {
            StatusBarIcon icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
                    Icon.createWithResource(
                            mContext, resourceId), 0, 0, contentDescription);
            holder = StatusBarIconHolder.fromIcon(icon);
            setIcon(index, holder);
        } else {
            holder.getIcon().icon = Icon.createWithResource(mContext, resourceId);
            holder.getIcon().contentDescription = contentDescription;
            handleSet(index, holder);
        }
		
    }
 public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
        boolean isNew = getIcon(index, holder.getTag()) == null;
        super.setIcon(index, holder);

        if (isNew) {
            addSystemIcon(index, holder);
        } else {
            handleSet(index, holder);
        }
    }
private void addSystemIcon(int index, StatusBarIconHolder holder) {
        String slot = getSlotName(index);
        int viewIndex = getViewIndex(index, holder.getTag());
        boolean blocked = mIconBlacklist.contains(slot);

        mIconLogger.onIconVisibility(getSlotName(index), holder.isVisible());
        mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, holder));
    }
  protected void onIconAdded(int index, String slot, boolean blocked,
                StatusBarIconHolder holder) {
            StatusIconDisplayable view = addHolder(index, slot, blocked, holder);
            mDarkIconDispatcher.addDarkReceiver((DarkReceiver) view);
        }
 protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked,
                StatusBarIconHolder holder) {
            switch (holder.getType()) {
                case TYPE_ICON:
                    return addIcon(index, slot, blocked, holder.getIcon());

                case TYPE_WIFI:
                    return addSignalIcon(index, slot, holder.getWifiState());

                case TYPE_MOBILE:
                    return addMobileIcon(index, slot, holder.getMobileState());
            }

            return null;
        }

    @VisibleForTesting
  protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
                StatusBarIcon icon) {
            StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
            view.set(icon);
            mGroup.addView(view, index, onCreateLayoutParams());
            return view;
        }

从上面的代码不难看出最后会调用addIcon,创建一个StatusBarIconView 添加到mGroup,而mGroup就是我们在所提到的R.id.statusIcons,也就是StatusIconContainer。到现在系统icon就添加到状态栏右边了。

状态栏流程的研究到此为止

你可能感兴趣的:(#,SystemUI,android,systemui,状态栏,StatusBar)