第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > Android SystemUI之StatusBar 状态栏(二)

Android SystemUI之StatusBar 状态栏(二)

时间:2020-11-23 13:18:47

相关推荐

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),说这么多还不如直接上图,这样大家看的比较清晰直观

从上图可以比较直观的看出来顶层树是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监听信息的servicemGroupManager = 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\statusbarmBarService = 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初始化的时候都是空或者0int[] switches = new int[9];//一些禁用列表ArrayList<IBinder> binders = new ArrayList<>();ArrayList<String> iconSlots = new ArrayList<>();//图标名称ArrayList<StatusBarIcon> 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 stateint 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 startIntentFilter wifiStatefilter = new IntentFilter();wifiStatefilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);mContext.registerReceiver(mWifiStateReceiver, wifiStatefilter);//yuanqi add endIVrManager 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 mDisplayMetricsupdateResources();updateTheme();//加载layout文件super_status_bar,mStatusBarWindowinflateStatusBarWindow(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);//加载短信通知的iconmStatusBarView = (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 onemHeadsUpAppearanceController.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_areamKeyguardIndicationController =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 visibilitysetAreThereNotifications();// TODO: Find better place for this callback.mBatteryController.addCallback(new BatteryStateChangeCallback() {@Overridepublic void onPowerSaveChanged(boolean isPowerSave) {mHandler.post(mCheckBarModes);if (mDozeServiceHost != null) {mDozeServiceHost.firePowerSaveChanged(isPowerSave);}}@Overridepublic 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 iconsmVolumeComponent = 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 broadcastsIntentFilter 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 windowsThreadedRenderer.overrideProperty("disableProfileBars", "true");// Private API call to make the shadows look better for RecentsThreadedRenderer.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的文件

<com.android.systemui.statusbar.phone.PhoneStatusBarViewxmlns:android="/apk/res/android"xmlns:systemui="/apk/res/com.android.systemui"android:layout_width="match_parent"android:layout_height="@dimen/status_bar_height"android:id="@+id/status_bar"android:background="@drawable/system_bar_background"android:orientation="vertical"android:focusable="false"android:descendantFocusability="afterDescendants"android:accessibilityPaneTitle="@string/status_bar"><ImageViewandroid:id="@+id/notification_lights_out"android:layout_width="@dimen/status_bar_icon_size"android:layout_height="match_parent"android:paddingStart="@dimen/status_bar_padding_start"android:paddingBottom="2dip"android:src="@drawable/ic_sysbar_lights_out_dot_small"android:scaleType="center"android:visibility="gone"/><LinearLayout android:id="@+id/status_bar_contents"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingStart="@dimen/status_bar_padding_start"android:paddingEnd="@dimen/status_bar_padding_end"android:orientation="horizontal"><ViewStubandroid:id="@+id/operator_name"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout="@layout/operator_name" /><FrameLayoutandroid:layout_height="match_parent"android:layout_width="0dp"android:layout_weight="1"><include layout="@layout/heads_up_status_bar_layout" /><!-- The alpha of the left side is controlled by PhoneStatusBarTransitions, and theindividual views are controlled by StatusBarManager disable flags DISABLE_CLOCK andDISABLE_NOTIFICATION_ICONS, respectively --><LinearLayoutandroid:id="@+id/status_bar_left_side"android:layout_height="match_parent"android:layout_width="match_parent"android:clipChildren="false"><com.android.systemui.statusbar.policy.Clockandroid:id="@+id/clock"android:layout_width="wrap_content"android:layout_height="match_parent"android:textAppearance="@style/TextAppearance.StatusBar.Clock"android:singleLine="true"android:paddingStart="@dimen/status_bar_left_clock_starting_padding"android:paddingEnd="@dimen/status_bar_left_clock_end_padding"android:gravity="center_vertical|start"/><com.android.systemui.statusbar.AlphaOptimizedFrameLayoutandroid:id="@+id/notification_icon_area"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="horizontal"android:clipChildren="false"/></LinearLayout></FrameLayout><!-- Space should cover the notch (if it exists) and let other views lay out around it --><android.widget.Spaceandroid:id="@+id/cutout_space_view"android:layout_width="0dp"android:layout_height="match_parent"android:gravity="center_horizontal|center_vertical"/><com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="horizontal"android:gravity="center_vertical|end"><include layout="@layout/system_icons" /></com.android.keyguard.AlphaOptimizedLinearLayout></LinearLayout><ViewStubandroid:id="@+id/emergency_cryptkeeper_text"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout="@layout/emergency_cryptkeeper_text"/></com.android.systemui.statusbar.phone.PhoneStatusBarView>

上面的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,这部分就是状态栏右边部分,里面包含了电池图标和系统状态图标

<LinearLayout xmlns:android="/apk/res/android"android:id="@+id/system_icons"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"><com.android.systemui.statusbar.phone.StatusIconContainer android:id="@+id/statusIcons"android:layout_width="0dp"android:layout_weight="1"android:layout_height="match_parent"android:paddingEnd="@dimen/signal_cluster_battery_padding"android:gravity="center_vertical"android:orientation="horizontal"/><com.android.systemui.BatteryMeterView android:id="@+id/battery"android:layout_height="match_parent"android:layout_width="wrap_content"android:clipToPadding="false"android:clipChildren="false" /></LinearLayout>

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

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

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

public void initNotificationIconArea(NotificationIconAreaControllernotificationIconAreaController) {ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);//短信通知iconmNotificationIconAreaInner =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 如下代码

<com.android.keyguard.AlphaOptimizedLinearLayoutxmlns:android="/apk/res/android"android:id="@+id/notification_icon_area_inner"android:layout_width="match_parent"android:layout_height="match_parent"android:clipChildren="false"><com.android.systemui.statusbar.phone.NotificationIconContainerandroid:id="@+id/notificationIcons"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_alignParentStart="true"android:gravity="center_vertical"android:orientation="horizontal"android:clipChildren="false"/></com.android.keyguard.AlphaOptimizedLinearLayout>

看到这边好像我们还没看到短信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 shownif (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 iconsmNotificationIconAreaController.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<NotificationData.Entry, StatusBarIconView> function,NotificationIconContainer hostLayout, boolean showAmbient, boolean hideDismissed,boolean hideRepliedMessages) {ArrayList<StatusBarIconView> 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<String, ArrayList<StatusBarIcon>> replacingIcons = new ArrayMap<>();ArrayList<View> 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<StatusBarIcon> statusBarIcons = replacingIcons.get(removedGroupKey);if (statusBarIcons == null) {statusBarIcons = new ArrayList<>();replacingIcons.put(removedGroupKey, statusBarIcons);}statusBarIcons.add(removedIcon.getStatusBarIcon());}toRemove.add(removedIcon);}}// removing all duplicatesArrayList<String> duplicates = new ArrayList<>();for (String key : replacingIcons.keySet()) {ArrayList<StatusBarIcon> 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 againhostLayout.removeTransientView(v);if (v.getParent() == null) {if (hideDismissed) {v.setOnDismissListener(mUpdateStatusBarIcons);}hostLayout.addView(v, i, params);}}hostLayout.setChangingViewPositions(true);// Re-sort notification iconsfinal 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管理类。管理StatusBarIconViewmDarkIconManager = 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父类LinearLayoutmClockView = mStatusBar.findViewById(R.id.clock);//时间iconshowSystemIconArea(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;}@VisibleForTestingprotected 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 statusmIconController.setIcon(mSlotEmbms, R.drawable.stat_sys_embms, null);mIconController.setIconVisibility(mSlotEmbms, false);// Alarm clockmIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);mIconController.setIconVisibility(mSlotAlarmClock, false);// zenmIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null);mIconController.setIconVisibility(mSlotZen, false);// volumemIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null);mIconController.setIconVisibility(mSlotVolume, false);updateVolumeZen();// castmIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);mIconController.setIconVisibility(mSlotCast, false);// hotspotmIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,mContext.getString(R.string.accessibility_status_bar_hotspot));mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());// managed profilemIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,mContext.getString(R.string.accessibility_managed_profile));mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible);// data savermIconController.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;}@VisibleForTestingprotected 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就添加到状态栏右边了。

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。