SystemUI源码分析之状态栏

一.界面分析

代码库:
/frameworks/base/services //services.jar
/frameworks/base/packages/SystemUI //SystemUI.apk
在SystemServer.java中调用startSystemUi启动

intent.setComponent(new ComponentName("com.android.systemui",
                "com.android.systemui.SystemUIService")); //启动SystemUIService,第一个参数为包名,第二个为Activity
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
        windowManager.onSystemUiStarted();
windowManager.onSystemUiStarted();//启动锁屏界面

SystemUIService的OnCreate会调用((SystemUIApplication) getApplication()).startServicesIfNeeded();

查看startServicesIfNeeded

public void startServicesIfNeeded() {
        String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents); //加载config_systemUIServiceComponents
        startServicesIfNeeded(names);//启动
    }

config_systemUIServiceComponents位于/frameworks/base/packages/SystemUI/res/values/config.xml,定义了各个activity,这些activity 均继承SystemUI.java

<string-array name="config_systemUIServiceComponents" translatable="false">
        <item>com.android.systemui.Dependency$DependencyCreator</item>
        <item>com.android.systemui.util.NotificationChannels</item> //创建SystemUI的通知Channel        
        <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
        <item>com.android.systemui.keyguard.KeyguardViewMediator</item> //锁屏
        <item>com.android.systemui.recents.Recents</item>  //最近任务
        <item>com.android.systemui.volume.VolumeUI</item>  //音量
        <item>com.android.systemui.stackdivider.Divider</item>  //分屏
        <item>com.android.systemui.SystemBars</item>   //状态栏
        <item>com.android.systemui.usb.StorageNotification</item>
        <item>com.android.systemui.power.PowerUI</item>  //电量
        <item>com.android.systemui.media.RingtonePlayer</item> //铃声播放
        <item>com.android.systemui.keyboard.KeyboardUI</item> //锁屏
        <item>com.android.systemui.pip.PipUI</item> //画中画
        <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item> //手机屏幕屏切圆角,模拟刘海屏        
        <item>@string/config_systemUIVendorServiceComponent</item>
        <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
        <item>com.android.systemui.LatencyTester</item>
        <item>com.android.systemui.globalactions.GlobalActionsComponent</item>//关机菜单        
        <item>com.android.systemui.ScreenDecorations</item>
        <item>com.android.systemui.biometrics.BiometricDialogImpl</item> //生物识别(指纹解锁,人脸识别等)
        <item>com.android.systemui.SliceBroadcastRelayHandler</item>
        <item>com.android.systemui.SizeCompatModeActivityController</item>
        <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item> //通知
        <item>com.android.systemui.theme.ThemeOverlayController</item>
    </string-array>

二.状态栏SystemBars

查看SystemBars的start方法,调用了createStatusBarFromConfig,创建了StatusBar对象

private void createStatusBarFromConfig() {
        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
        final String clsName = mContext.getString(R.string.config_statusBarComponent); //frameworks/base/packages/SystemUI/res/values/config.xml,值为com.android.systemui.statusbar.phone.StatusBar
        .....
            mStatusBar = (SystemUI) cls.newInstance();
        ...,..
        mStatusBar.mContext = mContext;
        mStatusBar.mComponents = mComponents;
        if (mStatusBar instanceof StatusBar) {
            SystemUIFactory.getInstance().getRootComponent()
                    .getStatusBarInjector()
                    .createStatusBar((StatusBar) mStatusBar);
        }
        mStatusBar.start(); //启动
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }

查看StatusBar的start方法,重点关注下面逻辑

mNetworkController = Dependency.get(NetworkController.class); //wifi或者数据图标相关,NetworkControllerImpl
 mBatteryController = Dependency.get(BatteryController.class);  //电池图标相关
createAndAddWindows(result);   //创建view
// Lastly, call to the icon policy to install/update all the icons.
        mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController);
        mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController);
 
//createAndAddWindows
 public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
        makeStatusBarView(result);
        ...
    }
protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
     inflateStatusBarWindow(context);  //R.layout.super_status_bar
    FragmentHostManager.get(mStatusBarWindow)  //顶部状态栏CollapsedStatusBarFragment
                .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
                    CollapsedStatusBarFragment statusBarFragment =
                            (CollapsedStatusBarFragment) fragment;
                    statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
      }).getFragmentManager()
                .beginTransaction()
                .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                        CollapsedStatusBarFragment.TAG)
                .commit();
      createNavigationBar(result);//底部导航栏
}

1.状态栏图标的添加StatusBarIconController

参考https://blog.csdn.net/qq_30295213/article/details/102900483
添加的icon定义在/frameworks/base/core/res/res/values/config.xml中的config_statusBarIcons,总共32个
在这里插入图片描述
代码中添加的icon位于PhoneStatusBarPolicy.java中的构造方法

updateTTY(); //tty,电传打字机
updateBluetooth(); //bluetooth
mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null); //alarm_clock,
mIconController.setIcon(mSlotZen, R.drawable.stat_sys_dnd, null); //zen
mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null); //volume
mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null); //cast
updateHotspotIcon(); //hotspot
mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status //managed_profile ,工作资料
mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver  //data_saver,省流模式
mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,  //  定位
mIconController.setIcon(mSlotSensorsOff, R.drawable.stat_sys_sensors_off //sensors_of 传感器关闭

2.网络相关图标的添加(NetworkController)

查看NetworkControllerImpl的构造方法

final SparseArray<MobileSignalController> mMobileSignalControllers = new SparseArray<>(); 
mDataUsageController = dataUsageController;
mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
                mCallbackHandler, this, mWifiManager);
mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);

最后通过mReceiverHandler.post(mRegisterListeners);注册相关监听,查看registerListeners

mobileSignalController.registerListener();
mobileSignalController.registerFiveGStateListener(mFiveGServiceClient);
mContext.registerReceiver(this, filter, null, mReceiverHandler);
updateMobileControllers();

当收到来自ConnectivityService.java中的CONNECTIVITY_ACTION广播时

updateConnectivity
->pushConnectivityToSignals
//pushConnectivityToSignals
 mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
 mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
2.1数据网络图标更新 (status_bar_mobile)
mobileSignalController.updateConnectivity
-->notifyListenersIfNecessary
-->notifyListeners
-->notifyListeners(mCallbackHandler) //NetworkControllerImpl中的mCallbackHandler

//notifyListeners主要逻辑如下

//图标状态,重点关注,用于判断显示什么样的图标(叉号,感叹号等),可定制显示图标
IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,getCurrentIconId(), contentDescription);
qsIcon = new IconState(mCurrentState.enabled && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
//下行
boolean activityIn = mCurrentState.dataConnected&& !mCurrentState.carrierNetworkChangeMode&& mCurrentState.activityIn;
//上行
boolean activityOut = mCurrentState.dataConnected&& !mCurrentState.carrierNetworkChangeMode && mCurrentState.activityOut;
//类型(LTE,NR)
int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon|| mConfig.alwaysShowNetworkTypeIcon) ? icons.mDataType : 0;
//Volte
int volteIcon = mConfig.showVolteIcon && isVolteSwitchOn() ? getVolteResId() : 0;
callback. setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
                activityIn, activityOut,volteIcon,
                dataContentDescription, description, icons.mIsWide,
                mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);  //callback为StatusBarSignalPolicy.java

其中mCurrentState是通过updateTelephony进行更新,mCurrentState的相关参数如下

// mCurrentState.enabled ,在构造方法中赋值
   mCurrentState.enabled = hasMobileData   //为mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
 
//mCurrentState.isEmergency, 在updateTelephony中赋值
   mCurrentState.isEmergency = isEmergencyOnly();  //调用mServiceState.isEmergencyOnly(),mServiceState来自onServiceStateChanged
 
//mCurrentState.airplaneMode,在NetworkControllerImpl中的updateAirplaneMode赋值
    boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
 
//mCurrentState.connected,在updateTelephony中赋值
    mCurrentState.connected = Utils.isInService(mServiceState)
 
//mCurrentState.dataConnected,在updateTelephony中赋值
    mCurrentState.dataConnected = mCurrentState.connected && (mDataState == TelephonyManager.DATA_CONNECTED || mMMSDataState == DataState.CONNECTED);
 
//mCurrentState.carrierNetworkChangeMode,在NetworkControllerImpl.java中初始化
      String carrierNetworkChange = args.getString("carriernetworkchange")
     boolean show = carrierNetworkChange.equals("show");
     controller.setCarrierNetworkChangeMode(show);
 
//mCurrentState.activityIn,mCurrentState.activityOut来自onDataActivity传进的参数
 
//mCurrentState.iconGroup   //重点关注,决定传进的参数typeIcon    

分析mCurrentState.iconGroup

//初始值,构造方法中
   mCurrentState.iconGroup = mDefaultIcons //  mDefaultIcons 来自mapIconSets
//mapIconSets
    !mConfig.showAtLeast3G 来判断是TelephonyIcons.G还是TelephonyIcons.THREE_G
//mConfig为创建NetworkControllerImpl传进的参数
//在updateTelephony中会根据注网状态来显示什么图标

分析getCurrentIconId(获取显示Icon的ID,决定显示哪个图标)

public int getCurrentIconId() {
       if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) {//运营商网络正在更新
           return SignalDrawable.getCarrierChangeState(getNumLevels());
       } else if (mCurrentState.connected) {  //已联网
           int level = mCurrentState.level;
           if (mInflateSignalStrengths) {
               level++;
           }
 
           boolean dataDisabled = mCurrentState.userSetup
                   && (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
                   || mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA);
           boolean noInternet = mCurrentState.inetCondition == 0;
           boolean cutOut = dataDisabled || noInternet;
           if (mConfig.hideNoInternetState) {
               cutOut = false;
           }
           return SignalDrawable.getState(level, getNumLevels(), cutOut); //cutOut为是否显示X号
       } else if (mCurrentState.enabled) {  //有插卡未联网
           return SignalDrawable.getEmptyState(getNumLevels());
       } else {
           return 0;
       }
   }

继续看callback. setMobileDataIndicators,实际调用的是StatusBarSignalPolicy的方法,其逻辑如下

public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
            int qsType, boolean activityIn, boolean activityOut, int volteIcon,
            String typeContentDescription, String description, boolean isWide,
            int subId, boolean roaming) {
        MobileIconState state = getState(subId);
        boolean typeChanged = statusType != state.typeId && (statusType == 0 || state.typeId == 0);//传进的statusType发生改变
        state.XXX=XXX;  //保存传进的参数
        //mSlotMobile为mobile
        mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates));//更新数据图标,重点关注
 
        if (typeChanged) {
                updateWifiIconWithState(wifiCopy); //更新wifi图标
            }
        }
    }
//先看wifi图标,mIconController为StatusBarIconControllerImpl.java
 private void updateWifiIconWithState(WifiIconState state) {
        if (state.visible && state.resId > 0) {
            mIconController.setSignalIcon(mSlotWifi, state);
            mIconController.setIconVisibility(mSlotWifi, true);
        } else {
            mIconController.setIconVisibility(mSlotWifi, false);
        }
    }
//设置数据图标
public void setMobileIcons(String slot, List<MobileIconState> iconStates) {
        Slot mobileSlot = getSlot(slot);
        int slotIndex = getSlotIndex(slot);
        Collections.reverse(iconStates);
        for (MobileIconState state : iconStates) {
            StatusBarIconHolder holder = mobileSlot.getHolderForTag(state.subId);
            if (holder == null) {
                holdseer = StatusBarIconHolder.fromMobileIconState(state);
                setIcon(slotIndex, holder);//重点关注
            } else {
                holder.setMobileState(state);  //设置
                handleSet(slotIndex, holder);
            }
        }
    }
//setIcon最终调用到StatusBarIconController中的子类TintedIconManager(或者DarkIconManager)中的onIconAdded
//CollapsedStatusBarFragment.java(顶部状态栏)传进的是DarkIconManager,KeyguardStatusBarView.java(锁屏)和QuickStatusBarHeader.java(下拉)传进的是TintedIconManager
//均调用到addHolder
 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;
        }

2.2 wifi图标

通过setWifiIndicators进行设置,来自WifiSignalController.java中的notifyListeners,其主要逻辑如下

public void notifyListeners(SignalCallback callback) {
        // only show wifi in the cluster if connected or if wifi-only
        boolean wifiVisible = mCurrentState.enabled
                && (mCurrentState.connected || !mHasMobileData);//wifi是否可见
        String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
        boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
        String contentDescription = getStringIfExists(getContentDescription());
        if (mCurrentState.inetCondition == 0) {
            contentDescription += ("," + mContext.getString(R.string.data_connection_no_internet));
        }
        IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);//依旧关注getCurrentIconId
        IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(),
                contentDescription);
        callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
                ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
                wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
    }
 public int getCurrentIconId() {
        if (mCurrentState.connected) {
            return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level];
        } else if (mCurrentState.enabled) {
            return getIcons().mSbDiscState;
        } else {
            return getIcons().mSbNullState;
        }
    }  

2.3以太网图标(status_bar_ethernet)

通过setEthernetIndicators进行设置,来自EthernetSignalController.java中的otifyListeners

2.4飞行模式(status_bar_airplane)

通过setIsAirplaneMode设置,来自NetworkControllerImpl.java中的notifyListeners()

2.5电池(status_bar_battery)

参考https://blog.csdn.net/xiaowang_lj/article/details/126763309

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值