SystemUI狀態(tài)欄wifi和數(shù)據(jù)icon顯示邏輯分析

今天我們來(lái)講講大家比較熟悉的狀態(tài)欄wifi icon和數(shù)據(jù)icon顯示邏輯。
一般在正常使用情況下,當(dāng)手機(jī)連接wifi的時(shí)候,狀態(tài)欄就會(huì)顯示wifi icon,而當(dāng)wifi斷開(kāi)的時(shí)候,狀態(tài)欄就會(huì)顯示4G 3G等等的數(shù)據(jù)icon。那么顯示wifi或者4G的依據(jù)是什么呢?手機(jī)在某些網(wǎng)絡(luò)狀態(tài)下,會(huì)不會(huì)有wifi和4G icon同時(shí)顯示的現(xiàn)象呢?下面我們就帶著這個(gè)疑問(wèn),去了解下wifi和4G icon顯示的邏輯。

  1. 首先我們看下wifi的顯示邏輯
    @Override
    public void notifyListeners(SignalCallback callback) {
        // only show wifi in the cluster if connected or if wifi-only
        boolean wifiVisible = mCurrentState.enabled
                && (mCurrentState.connected || !mHasMobileData);
        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.accessibility_quick_settings_no_internet));
        }

        IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);

在WifiSignalController中wifiVisible控制著wifi的visibility,而wifiVisible主要是受mCurrentState.enabled和mCurrentState.connected影響(mHasMobileData這個(gè)值可以忽略,這個(gè)值代表是否支持?jǐn)?shù)據(jù)網(wǎng)絡(luò),顯然手機(jī)項(xiàng)目這個(gè)值始終是true)

   public void handleBroadcast(Intent intent) {
        String action = intent.getAction();
        if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
            state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                    WifiManager.WIFI_STATE_UNKNOWN);
            enabled = state == WifiManager.WIFI_STATE_ENABLED;
            Log.d("SIGNALICON", TAG + ",handleBroadcast,WIFI_STATE,state = " + state + ",enabled = " + enabled);
        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
            final NetworkInfo networkInfo = (NetworkInfo)
                    intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
            connecting = networkInfo != null && !networkInfo.isConnected()
                    && networkInfo.isConnectedOrConnecting();
            connected = networkInfo != null && networkInfo.isConnected();
            Log.d("SIGNALICON", TAG + ",handleBroadcast,NETWORK_STATE,connecting = " + connecting + ",connected = " + connected);
            .........................
            .........................
            .........................
            

如上就是在WifiStatusTracker中通過(guò)廣播消息取到的wifi的狀態(tài),到這里wifi的顯示就講完了,邏輯還是很簡(jiǎn)單清晰的

  1. 下面我們就需要重點(diǎn)關(guān)注下數(shù)據(jù)icon的顯示邏輯了
      final boolean dataDisabled = (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED)
                && mCurrentState.userSetup;
      boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
        Log.d("SIGNALICON", mTag + ",notifyListeners======dataDisabled = " + dataDisabled
                + ",dataConnected = " + mCurrentState.dataConnected + ",showDataIcon= " + showDataIcon);
        IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
                getCurrentIconId(), contentDescription);

        int qsTypeIcon = 0;
        IconState qsIcon = null;
        String description = null;
        // Only send data sim callbacks to QS.
        if (mCurrentState.dataSim) {
            qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
            qsIcon = new IconState(mCurrentState.enabled
                    && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
            description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
        }
        boolean activityIn = mCurrentState.dataConnected
                && !mCurrentState.carrierNetworkChangeMode
                && mCurrentState.activityIn;
        boolean activityOut = mCurrentState.dataConnected
                && !mCurrentState.carrierNetworkChangeMode
                && mCurrentState.activityOut;
        showDataIcon &= mCurrentState.isDefault || dataDisabled;
        Log.d("SIGNALICON", mTag + ",notifyListeners,dataDisabled = " + dataDisabled
                + ",isDefault = " + mCurrentState.isDefault + ",showDataIcon= " + showDataIcon);

        Log.d("SIGNALICON", mTag + ",notifyListeners,showDataIcon= " + showDataIcon + ",mStyle = " + mStyle);
        int typeIcon = (showDataIcon && mStyle == STATUS_BAR_STYLE_ANDROID_DEFAULT) ? icons.mDataType : 0;
        int dataActivityId = showDataIcon && !showMobileActivity() ? icons.mActivityId : 0;
        callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
                activityIn, activityOut, dataActivityId,
                icons.mStackedDataIcon, icons.mStackedVoiceIcon,
                dataContentDescription, description, icons.mIsWide,
                mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming,
                networkIcon, volteIcon, showDataIcon);

如上,在MobileSignalController中,就是核心的數(shù)據(jù)icon的顯示,其中我們關(guān)注的是typeIcon,這個(gè)icon就是顯示的4G,3G icon,所以我們?cè)敿?xì)分析下typeIcon 的邏輯

int typeIcon = (showDataIcon && mStyle == STATUS_BAR_STYLE_ANDROID_DEFAULT) ? icons.mDataType : 0;

從這里我們可以清晰的看到,typeIcon 是受showDataIcon的控制

boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;

showDataIcon &= mCurrentState.isDefault || dataDisabled;

可以看到showDataIcon主要有兩處進(jìn)行了賦值,那么這兩次賦值分別代表了什么不同的意義呢?我們接著往下看

在updateTelephony()函數(shù)中

    if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
            mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
        } else {
            mCurrentState.iconGroup = mDefaultIcons;
        }
        mCurrentState.dataConnected = mCurrentState.connected
                && mDataState == TelephonyManager.DATA_CONNECTED;

        Log.d("SIGNALICON", mTag + ",updateTelephony,connected = " + mCurrentState.connected
                + ", mDataState = " + mDataState + ",dataConnected = " + mCurrentState.dataConnected);

        mCurrentState.roaming = isRoaming();
        if (isCarrierNetworkChangeActive()) {
            mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
        } else if (isDataDisabled()) {
            mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
        }

找到了mCurrentState.dataConnected和mCurrentState.iconGroup賦值的地方,我們主要關(guān)注mDataState 即可。

在class MobilePhoneStateListener extends PhoneStateListener {}中我們找到了mDataState 的出處

    @Override
        public void onDataConnectionStateChanged(int state, int networkType) {
            mDataState = state;
            mDataNetType = networkType;
            Log.d("SIGNALICON", mTag + ",onDataConnectionStateChanged,state = " + state
                    + ", networkType = " + networkType);
            if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
                    mServiceState.isUsingCarrierAggregation()) {
                mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
            }
            updateTelephony();
        }

可見(jiàn)mDataState 是從PhoneStateListener callback中上報(bào)的,該值主要對(duì)應(yīng)了不同的連接狀態(tài),可以看下framework定義。TelephonyManager.java中

    ** Data connection state: Unknown.  Used before we know the state.
     * @hide
     */
    public static final int DATA_UNKNOWN        = -1;
    /** Data connection state: Disconnected. IP traffic not available. */
    public static final int DATA_DISCONNECTED   = 0;
    /** Data connection state: Currently setting up a data connection. */
    public static final int DATA_CONNECTING     = 1;
    /** Data connection state: Connected. IP traffic should be available. */
    public static final int DATA_CONNECTED      = 2;
    /** Data connection state: Suspended. The connection is up, but IP
     * traffic is temporarily unavailable. For example, in a 2G network,
     * data activity may be suspended when a voice call arrives. */
    public static final int DATA_SUSPENDED      = 3;

實(shí)際上這個(gè)callback就是用戶(hù)主動(dòng)開(kāi)啟和關(guān)閉數(shù)據(jù)業(yè)務(wù)的時(shí)候,framework上報(bào)的流程,我順帶加了點(diǎn)log有助于邏輯分析,下面我們就分幾種情況看下對(duì)應(yīng)的log

  • 開(kāi)啟數(shù)據(jù)業(yè)務(wù)
09-11 16:38:45.477  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),onDataConnectionStateChanged,state = 2, networkType = 13
09-11 16:38:45.509  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),updateTelephony,connected = true, mDataState = 2,dataConnected = true
09-11 16:38:45.517  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:38:45.518  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = false,showDataIcon= false
09-11 16:38:45.519  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,showDataIcon= false,mStyle = 0
09-11 16:38:45.529  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),updateTelephony,connected = true, mDataState = 2,dataConnected = true
09-11 16:38:45.572  1524  1755 D SIGNALICON: NetworkController,updateConnectivity update transportType
09-11 16:38:45.574  1524  1755 D SIGNALICON: NetworkController,updateConnectivity======transportType = 0
09-11 16:38:45.575  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:38:45.576  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = true,showDataIcon= true
09-11 16:38:45.576  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,showDataIcon= true,mStyle = 0

當(dāng)主動(dòng)開(kāi)啟數(shù)據(jù)業(yè)務(wù)的時(shí)候,callback上報(bào)了state = 2, networkType = 13狀態(tài),state代表數(shù)據(jù)連接狀態(tài)而networkType 則代表當(dāng)前的網(wǎng)絡(luò)類(lèi)型(3G和4G等等),緊接著updateTelephony函數(shù)中會(huì)根據(jù)state設(shè)置mCurrentState.dataConnected狀態(tài),最后在notifyListeners根據(jù)mCurrentState.dataConnected的狀態(tài)設(shè)置了showDataIcon的值

  • 關(guān)閉數(shù)據(jù)業(yè)務(wù)
09-11 16:40:32.840  1524  1755 D SIGNALICON: NetworkController,updateConnectivity update transportType
09-11 16:40:32.843  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:40:32.843  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = false,showDataIcon= false
09-11 16:40:32.843  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,showDataIcon= false,mStyle = 0
09-11 16:40:32.943  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),updateTelephony,connected = true, mDataState = 2,dataConnected = true
09-11 16:40:33.172  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),onDataConnectionStateChanged,state = 0, networkType = 13
09-11 16:40:33.181  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),updateTelephony,connected = true, mDataState = 0,dataConnected = false
09-11 16:40:33.185  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = false,showDataIcon= false
09-11 16:40:33.185  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = false,showDataIcon= false
09-11 16:40:33.185  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,showDataIcon= false,mStyle = 0
09-11 16:40:36.461  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),updateTelephony,connected = true, mDataState = 0,dataConnected = false

關(guān)閉數(shù)據(jù)業(yè)務(wù)的流程,大致和開(kāi)啟式一致的,只是中間的狀態(tài)是相反的

以上就是我們第二點(diǎn)要講的,數(shù)據(jù)業(yè)務(wù)開(kāi)關(guān)的流程,說(shuō)白了狀態(tài)欄就是依據(jù)onDataConnectionStateChanged callback來(lái)刷新UI,邏輯也是比較清晰明了的。

細(xì)心的你可能就會(huì)發(fā)現(xiàn),showDataIcon 不是有兩處賦值的地方嗎?

boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
showDataIcon &= mCurrentState.isDefault || dataDisabled;

onDataConnectionStateChanged callback 只與第一次的賦值有關(guān)聯(lián),那第二次的賦值又與什么有關(guān)聯(lián)呢?
下面就是我們要重點(diǎn)講的第三點(diǎn),我們來(lái)看看第二個(gè)賦值中的mCurrentState.isDefault是何方神圣,
這也是寫(xiě)本文的最終用意。

  1. 數(shù)據(jù)業(yè)務(wù)的被動(dòng)刷新
    你有否想過(guò),在數(shù)據(jù)業(yè)務(wù)開(kāi)啟的情況下,手機(jī)又連接了wifi,這時(shí)狀態(tài)欄顯示了wifi icon而4G icon是怎么消失的呢?
    首先我們看下wifi開(kāi)啟和關(guān)閉的log
  • wifi開(kāi)啟
09-11 16:42:34.264  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast,WIFI_STATE,state = 2, enabled = false
09-11 16:42:34.278  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast,WIFI_STATE,state = 3, enabled = true
09-11 16:42:37.596  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:42:37.596  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = true,showDataIcon= true
09-11 16:42:37.596  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,showDataIcon= true,mStyle = 0
09-11 16:42:39.608  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:42:39.609  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = true,showDataIcon= true
09-11 16:42:39.609  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,showDataIcon= true,mStyle = 0
09-11 16:42:56.984  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast,NETWORK_STATE,connected = true
09-11 16:42:57.096  1524  1755 D SIGNALICON: NetworkController,updateConnectivity update transportType
09-11 16:42:57.097  1524  1755 D SIGNALICON: NetworkController,updateConnectivity======transportType = 1
09-11 16:42:57.101  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:42:57.101  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = false,showDataIcon= false
09-11 16:42:57.101  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,showDataIcon= false,mStyle = 0

  • wifi關(guān)閉
09-11 16:44:26.877  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast------>NETWORK_STATE,connected = false
09-11 16:44:26.913  1524  1755 D SIGNALICON: NetworkController,updateConnectivity update transportType
09-11 16:44:26.974  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast------>WIFI_STATE,state = 0, enabled = false
09-11 16:44:27.007  1524  1755 D SIGNALICON: NetworkController,updateConnectivity update transportType
09-11 16:44:27.010  1524  1755 D SIGNALICON: NetworkController,updateConnectivity======transportType = 0
09-11 16:44:27.012  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:44:27.012  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = true,showDataIcon= true
09-11 16:44:27.012  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,showDataIcon= true,mStyle = 0
09-11 16:44:27.622  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast------>WIFI_STATE,state = 1, enabled = false
09-11 16:44:28.265  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:44:28.266  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = true,showDataIcon= true
09-11 16:44:28.266  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,showDataIcon= true,mStyle = 0

我們截取log其中一段看下

wifi 開(kāi)啟
09-11 16:42:56.984  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast,NETWORK_STATE,connected = true
NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:42:57.101  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = false,showDataIcon= false

wifi 關(guān)閉
09-11 16:44:26.974  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast------>WIFI_STATE,state = 0, enabled = false
NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:44:27.012  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = true,showDataIcon= true
09-11 16:44:27.012  1524  1755 D SIGNALICON: 

在wifi開(kāi)啟或者關(guān)閉的時(shí)候,showDataIcon第一次賦值的地方始終是true,這也是正常的,因?yàn)閿?shù)據(jù)業(yè)務(wù)本來(lái)就是開(kāi)著的,而且onDataConnectionStateChanged callback也沒(méi)有上報(bào)刷新,然后到了第二次showDataIcon賦值的時(shí)候卻出現(xiàn)變化了
showDataIcon &= mCurrentState.isDefault || dataDisabled;
邏輯里面是這么定義的,log里面也能看到,mCurrentState.isDefault導(dǎo)致了最后showDataIcon發(fā)生了變化。我們接著往下看

    @Override
    public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
        boolean isValidated = validatedTransports.get(mTransportType);
        mCurrentState.isDefault = connectedTransports.get(mTransportType);
        // Only show this as not having connectivity if we are default.
        mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0;
        notifyListenersIfNecessary();
    }

還是在MobileSignalController中,我們找到了mCurrentState.isDefault的出處,看過(guò)我上一篇狀態(tài)欄信號(hào)分析的同學(xué)
SystemUI狀態(tài)欄wifi和sim icon顯示"x"號(hào)或者"!"號(hào)現(xiàn)象分析
對(duì)這個(gè)函數(shù)一定很清楚了,有興趣的可以再看下熟悉這之間的流程,那么我們長(zhǎng)話(huà)短說(shuō)。

在NetworkControllerImpl中,當(dāng)接收到ConnectivityManager.CONNECTIVITY_ACTION或者ConnectivityManager.INET_CONDITION_ACTION廣播的時(shí)候,觸發(fā)了updateConnectivity的刷新

/**
     * Update the Inet conditions and what network we are connected to.
     */
    private void updateConnectivity() {
        mConnectedTransports.clear();
        mValidatedTransports.clear();
        Log.d("SIGNALICON", TAG + ",updateConnectivity update transportType");
        for (NetworkCapabilities nc :
                mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
            for (int transportType : nc.getTransportTypes()) {
                Log.d("SIGNALICON", TAG + ",updateConnectivity======transportType = " + transportType);
                mConnectedTransports.set(transportType);
                if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
                    mValidatedTransports.set(transportType);
                }
            }
        }

        if (CHATTY) {
            Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports);
            Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
        }

        mInetCondition = !mValidatedTransports.isEmpty();

        pushConnectivityToSignals();
    }

/**
     * Pushes the current connectivity state to all SignalControllers.
     */
    private void pushConnectivityToSignals() {
        // We want to update all the icons, all at once, for any condition change
        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
            mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
        }
        mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
        mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
    }

到這里我們就找到了mCurrentState.isDefault = connectedTransports.get(mTransportType)實(shí)現(xiàn)的邏輯,就是在收到信號(hào)刷新廣播消息的時(shí)候,通過(guò)NetworkCapabilities中獲取了transportType,而MobileSignalController在初始化的時(shí)候就傳入了需要的數(shù)據(jù)類(lèi)型NetworkCapabilities.TRANSPORT_CELLULAR

public MobileSignalController(Context context, Config config, boolean hasMobileData,
            TelephonyManager phone, CallbackHandler callbackHandler,
            NetworkControllerImpl networkController, SubscriptionInfo info,
            SubscriptionDefaults defaults, Looper receiverLooper) {
        super("MobileSignalController(" + info.getSubscriptionId() + "_" + info.getSimSlotIndex() + ")", context,
                NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
                networkController);
                ................
                ................    

SignalController對(duì)mTransportType進(jìn)行了賦值

public SignalController(String tag, Context context, int type, CallbackHandler callbackHandler,
            NetworkControllerImpl networkController) {
        mTag = TAG + "." + tag;
        mNetworkController = networkController;
        mTransportType = type;
        ...........
        ...........

NetworkCapabilities中定義了信號(hào)類(lèi)型的值:

/**
     * Representing the transport type.  Apps should generally not care about transport.  A
     * request for a fast internet connection could be satisfied by a number of different
     * transports.  If any are specified here it will be satisfied a Network that matches
     * any of them.  If a caller doesn't care about the transport it should not specify any.
     */
    private long mTransportTypes;

    /**
     * Indicates this network uses a Cellular transport.
     */
    public static final int TRANSPORT_CELLULAR = 0;

    /**
     * Indicates this network uses a Wi-Fi transport.
     */
    public static final int TRANSPORT_WIFI = 1;

    /**
     * Indicates this network uses a Bluetooth transport.
     */
    public static final int TRANSPORT_BLUETOOTH = 2;
    

我們?cè)俳Y(jié)合log確認(rèn)下:

wifi 開(kāi)啟
09-11 16:42:56.984  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast,NETWORK_STATE,connected = true
09-11 16:42:57.096  1524  1755 D SIGNALICON: NetworkController,updateConnectivity update transportType
09-11 16:42:57.097  1524  1755 D SIGNALICON: NetworkController,updateConnectivity======transportType = 1
09-11 16:42:57.101  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:42:57.101  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = false,showDataIcon= false

wifi 關(guān)閉
09-11 16:44:26.877  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast------>NETWORK_STATE,connected = false
09-11 16:44:26.913  1524  1755 D SIGNALICON: NetworkController,updateConnectivity update transportType
09-11 16:44:26.974  1524  1755 D SIGNALICON: WifiStatusTracker,handleBroadcast------>WIFI_STATE,state = 0, enabled = false
09-11 16:44:27.007  1524  1755 D SIGNALICON: NetworkController,updateConnectivity update transportType
09-11 16:44:27.010  1524  1755 D SIGNALICON: NetworkController,updateConnectivity======transportType = 0
09-11 16:44:27.012  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners======dataDisabled = false,dataConnected = true,showDataIcon= true
09-11 16:44:27.012  1524  1755 D SIGNALICON: NetworkController.MobileSignalController(2_1),notifyListeners,dataDisabled = false,isDefault = true,showDataIcon= true

在wifi連接的時(shí)候上報(bào)了transportType = 1,導(dǎo)致isDefault = false;而wifi斷開(kāi),數(shù)據(jù)連接上時(shí),上報(bào)了transportType = 0,導(dǎo)致isDefault = true,log和我們的分析過(guò)程是完全吻合的。

以上systemui模塊刷新wifi和數(shù)據(jù)icon的分析就完結(jié)了,總結(jié)下:

  • 當(dāng)wifi和數(shù)據(jù)連接同時(shí)打開(kāi),wifi連接的時(shí)候,framework會(huì)通過(guò)ConnectivityManager.CONNECTIVITY_ACTION或者ConnectivityManager.INET_CONDITION_ACTION廣播,觸發(fā)了updateConnectivity的刷新,然后取到了transportType = 1,從而isDefault = false,MobileSignalController中showDataIcon = fase,數(shù)據(jù)icon就隱藏了
  • 當(dāng)wifi和數(shù)據(jù)連接同時(shí)打開(kāi),wifi斷開(kāi),數(shù)據(jù)連接的時(shí)候,framework會(huì)也通過(guò)ConnectivityManager.CONNECTIVITY_ACTION或者ConnectivityManager.INET_CONDITION_ACTION廣播,觸發(fā)了updateConnectivity的刷新,然后取到了transportType = 0,從而isDefault = true,MobileSignalController中showDataIcon = true,數(shù)據(jù)icon就顯示了。

項(xiàng)目開(kāi)發(fā)中有時(shí)候也會(huì)遇到wifi連接上了,wifi和4G同時(shí)顯示的現(xiàn)象
通過(guò)上面的分析,我們也就比較容易定位問(wèn)題了,加點(diǎn)log確認(rèn)下,當(dāng)時(shí)wifi connected = true的時(shí)候,updateConnectivity是不是也取到了transportType = 0的狀態(tài),從項(xiàng)目經(jīng)驗(yàn)中看90%是因?yàn)檫@個(gè)原因,貌似Android有這樣一個(gè)機(jī)制,當(dāng)wifi信號(hào)很微弱的時(shí)候,會(huì)自動(dòng)切換到數(shù)據(jù)流量,以免影響用戶(hù)體驗(yàn)。此時(shí)就需要framework協(xié)助進(jìn)一步確認(rèn)了

如果想進(jìn)階了解下framework上報(bào)的流程,各位看官可以跟著往下走;當(dāng)然如果覺(jué)得比較枯燥乏味,可以拿好貴重物品歡快的離場(chǎng)了。

  1. framework更新wifi和數(shù)據(jù)信號(hào)的流程

既然wifi和數(shù)據(jù)顯示的邏輯是受NetworkCapabilities 中的 TRANSPORT_CELLULAR和TRANSPORT_WIFI影響,而獲取這個(gè)狀態(tài)的入口是updateConnectivity函數(shù)

/**
     * Update the Inet conditions and what network we are connected to.
     */
    private void updateConnectivity() {
        mConnectedTransports.clear();
        mValidatedTransports.clear();
        for (NetworkCapabilities nc :
                mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
            for (int transportType : nc.getTransportTypes()) {
                mConnectedTransports.set(transportType);
                .....................................
    

那我們就從getDefaultNetworkCapabilitiesForUser和getTransportTypes它們?nèi)胧?/p>

在ConnectivityService中我們找到了getDefaultNetworkCapabilitiesForUser的實(shí)現(xiàn)

    @Override
    public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
        // The basic principle is: if an app's traffic could possibly go over a
        // network, without the app doing anything multinetwork-specific,
        // (hence, by "default"), then include that network's capabilities in
        // the array.
        //
        // In the normal case, app traffic only goes over the system's default
        // network connection, so that's the only network returned.
        //
        // With a VPN in force, some app traffic may go into the VPN, and thus
        // over whatever underlying networks the VPN specifies, while other app
        // traffic may go over the system default network (e.g.: a split-tunnel
        // VPN, or an app disallowed by the VPN), so the set of networks
        // returned includes the VPN's underlying networks and the system
        // default.
        enforceAccessPermission();

        HashMap<Network, NetworkCapabilities> result = new HashMap<Network, NetworkCapabilities>();

        NetworkAgentInfo nai = getDefaultNetwork();
        NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
        if (nc != null) {
            result.put(nai.network, nc);
        }
        ....................
   

這個(gè)函數(shù)中NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai)就是從NetworkAgentInfo把信息取出來(lái),最終給NetworkCapabilities設(shè)置mTransportTypes的地方

private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
        if (nai != null) {
            synchronized (nai) {
                if (nai.networkCapabilities != null) {
                    return new NetworkCapabilities(nai.networkCapabilities);
                }
            }
        }
        return null;
    }   

我們看NetworkCapabilities類(lèi)中的以下兩個(gè)函數(shù)

public NetworkCapabilities(NetworkCapabilities nc) {
        if (nc != null) {
            mNetworkCapabilities = nc.mNetworkCapabilities;
            mTransportTypes = nc.mTransportTypes;
            mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
            mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
            mNetworkSpecifier = nc.mNetworkSpecifier;
            mSignalStrength = nc.mSignalStrength;
        }
    }
   
/**
     * Gets all the transports set on this {@code NetworkCapability} instance.
     *
     * @return an array of {@code NetworkCapabilities.TRANSPORT_*} values
     *         for this instance.
     * @hide
     */
    public int[] getTransportTypes() {
        return BitUtils.unpackBits(mTransportTypes);
    }
   

好了到這里,我們就找到了getTransportTypes的實(shí)現(xiàn)

下面就主要關(guān)注ConnectivityService類(lèi)中g(shù)etDefaultNetworkCapabilitiesForUser函數(shù)是如何取到getDefaultNetwork()數(shù)據(jù)的的,因?yàn)楹竺娴倪壿嫸际菑倪@個(gè)函數(shù)中取數(shù)據(jù)的

private NetworkAgentInfo getDefaultNetwork() {
        return getNetworkForRequest(mDefaultRequest.requestId);
    }
    
private NetworkAgentInfo getNetworkForRequest(int requestId) {
        synchronized (mNetworkForRequestId) {
            return mNetworkForRequestId.get(requestId);
        }
    }
    
private void setNetworkForRequest(int requestId, NetworkAgentInfo nai) {
        synchronized (mNetworkForRequestId) {
            mNetworkForRequestId.put(requestId, nai);
        }
    }
/**
     * NetworkAgentInfo supporting a request by requestId.
     * These have already been vetted (their Capabilities satisfy the request)
     * and the are the highest scored network available.
     * the are keyed off the Requests requestId.
     */
    // NOTE: Accessed on multiple threads, must be synchronized on itself.
    @GuardedBy("mNetworkForRequestId")
    private final SparseArray<NetworkAgentInfo> mNetworkForRequestId =
            new SparseArray<NetworkAgentInfo>();
   

在上面的函數(shù)中我們找到了mNetworkForRequestId就是一個(gè)SparseArray,setNetworkForRequest給mNetworkForRequestId賦值,getNetworkForRequest負(fù)責(zé)取值。

  • 信號(hào)類(lèi)型的初始化

下面我們關(guān)注setNetworkForRequest函數(shù)是哪里調(diào)用,然后往里面?zhèn)髦档?我們就能夠找到出處了

private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork,
            ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
            .................
            newNetwork.unlingerRequest(nri.request);
                    setNetworkForRequest(nri.request.requestId, newNetwork);
                    if (!newNetwork.addRequest(nri.request)) {
                        Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request);
                    }
                    addedRequests.add(nri);
            .................        
            }
            
private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {

            ................
            updateSignalStrengthThresholds(networkAgent, "CONNECT", null);

            // Consider network even though it is not yet validated.
            final long now = SystemClock.elapsedRealtime();
            rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);

            // This has to happen after matching the requests, because callbacks are just requests.
            notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
            .................
}

我們看到在updateNetworkInfo中設(shè)置了最終的NetworkCapabilities,接著往下看

private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
        if (VDBG) log("Got NetworkAgent Messenger");
        mNetworkAgentInfos.put(na.messenger, na);
        synchronized (mNetworkForNetId) {
            mNetworkForNetId.put(na.network.netId, na);
        }
        na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
        NetworkInfo networkInfo = na.networkInfo;
        na.networkInfo = null;
        updateNetworkInfo(na, networkInfo);
    }

private class InternalHandler extends Handler {
        public InternalHandler(Looper looper) {
            super(looper);
        }
        
    case EVENT_REGISTER_NETWORK_AGENT: {
                    handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
                    break;
                }

public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
            LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
            int currentScore, NetworkMisc networkMisc) {
        enforceConnectivityInternalPermission();

        LinkProperties lp = new LinkProperties(linkProperties);
        lp.ensureDirectlyConnectedRoutes();
        // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
        // satisfies mDefaultRequest.
        final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
                new Network(reserveNetId()), new NetworkInfo(networkInfo), lp,
                new NetworkCapabilities(networkCapabilities), currentScore,
                mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
        synchronized (this) {
            nai.networkMonitor.systemReady = mSystemReady;
        }
        addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network,
                networkInfo.getExtraInfo());
        if (DBG) log("registerNetworkAgent " + nai);
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
        return nai.network.netId;
    }

在registerNetworkAgent中完成了updateNetworkInfo的設(shè)置,仿佛離答案越來(lái)越近了有木有,那么這個(gè)函數(shù)是怎么設(shè)置的呢

public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
            NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
        super(looper);
        LOG_TAG = logTag;
        mContext = context;
        if (ni == null || nc == null || lp == null) {
            throw new IllegalArgumentException();
        }

        if (VDBG) log("Registering NetworkAgent");
        ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
                Context.CONNECTIVITY_SERVICE);
        netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
                new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
    }

在NetworkAgent.java中我們找到了答案,就是在NetworkAgent初始化的時(shí)候注冊(cè)的。我們看下NetworkAgent的注釋

/**
 * A Utility class for handling for communicating between bearer-specific
 * code and ConnectivityService.
 *
 * A bearer may have more than one NetworkAgent if it can simultaneously
 * support separate networks (IMS / Internet / MMS Apns on cellular, or
 * perhaps connections with different SSID or P2P for Wi-Fi).
 *
 * @hide
 */
public abstract class NetworkAgent extends Handler {}

英文大意就是:
用于處理bearer-specific code 和 ConnectivityService通信的實(shí)用類(lèi),如果這個(gè)bearer可以承載多個(gè)網(wǎng)絡(luò)的話(huà),那它就會(huì)有多個(gè)NetworkAgent,比如 (IMS / Internet / MMS Apns on cellular, or perhaps connections with different SSID or P2P for Wi-Fi)

到這里我們就能夠大概猜到了,每個(gè)網(wǎng)絡(luò)類(lèi)型應(yīng)該就對(duì)應(yīng)著一個(gè)NetworkAgent,是不是醬紫呢?我們接著往下找

private class WifiNetworkAgent extends NetworkAgent {
        public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni,
                NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
            super(l, c, TAG, ni, nc, lp, score, misc);
        }
        .............
}
        
class L2ConnectedState extends State {
        @Override
        public void enter() {
            mRssiPollToken++;
            if (mEnableRssiPolling) {
                sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0);
            }
            if (mNetworkAgent != null) {
                loge("Have NetworkAgent when entering L2Connected");
                setNetworkDetailedState(DetailedState.DISCONNECTED);
            }
            setNetworkDetailedState(DetailedState.CONNECTING);

            mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext,
                    "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter,
                    mLinkProperties, 60, mNetworkMisc);
           .............
}

public WifiStateMachine(Context context, FrameworkFacade facade, Looper looper,
                            UserManager userManager, WifiInjector wifiInjector,
                            BackupManagerProxy backupManagerProxy, WifiCountryCode countryCode,
                            WifiNative wifiNative,
                            WrongPasswordNotifier wrongPasswordNotifier) {
                            
        .......................
        mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
        mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        mNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(1024 * 1024);
        mNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(1024 * 1024);
        .......................
                            }

在WifiStateMachine.java中發(fā)現(xiàn)了初始化NetworkAgent 的地方,我們看到了熟悉的身影
mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
終于我們找到設(shè)置TRANSPORT_WIFI的地方

private class DcNetworkAgent extends NetworkAgent {
        public DcNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni,
                NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
            super(l, c, TAG, ni, nc, lp, score, misc);
        }
        .............
}
        
/**
     * The state machine is connected, expecting an EVENT_DISCONNECT.
     */
    private class DcActiveState extends State {
        @Override public void enter() {
                .............
            final NetworkMisc misc = new NetworkMisc();
            final CarrierSignalAgent carrierSignalAgent = mPhone.getCarrierSignalAgent();
            if (carrierSignalAgent.hasRegisteredReceivers(TelephonyIntents
                    .ACTION_CARRIER_SIGNAL_REDIRECTED)) {
                // carrierSignal Receivers will place the carrier-specific provisioning notification
                misc.provisioningNotificationDisabled = true;
            }
            misc.subscriberId = mPhone.getSubscriberId();

            setNetworkRestriction();
            mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
                    "DcNetworkAgent", mNetworkInfo, getNetworkCapabilities(), mLinkProperties,
                    50, misc);
           .............
}

NetworkCapabilities getNetworkCapabilities() {
        NetworkCapabilities result = new NetworkCapabilities();
        result.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
        .......................
                            
                            }

同理在數(shù)據(jù)網(wǎng)絡(luò)DataConnection.java初始化的時(shí)候我們也找到了result.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)設(shè)置的地方

到這里初始化的地方就看的差不多了,下面我們?cè)倭私庀滦盘?hào)變化時(shí)刷新的數(shù)據(jù),NetworkAgentInfo是如何取到的。

  • 信號(hào)類(lèi)型的更新

我們?cè)倩氐紺onnectivityService中

private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
        final NetworkInfo.State state = newInfo.getState();
        NetworkInfo oldInfo = null;
        final int oldScore = networkAgent.getCurrentScore();
        synchronized (networkAgent) {
            oldInfo = networkAgent.networkInfo;
            networkAgent.networkInfo = newInfo;
        }
        notifyLockdownVpn(networkAgent);
        .....................
}


private void maybeHandleNetworkAgentMessage(Message msg) {
            NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
            if (nai == null) {
                if (VDBG) {
                    log(String.format("%s from unknown NetworkAgent", eventName(msg.what)));
                }
                return;
            }
            ....................
            case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
                    NetworkInfo info = (NetworkInfo) msg.obj;
                    updateNetworkInfo(nai, info);
                    break;
                }
            ....................

}

private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
        if (VDBG) log("Got NetworkAgent Messenger");
        mNetworkAgentInfos.put(na.messenger, na);
        synchronized (mNetworkForNetId) {
            mNetworkForNetId.put(na.network.netId, na);
        }
        na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
        NetworkInfo networkInfo = na.networkInfo;
        na.networkInfo = null;
        updateNetworkInfo(na, networkInfo);
    }

NetworkAgent.java
/**
     * Called by the bearer code when it has new NetworkInfo data.
     */
    public void sendNetworkInfo(NetworkInfo networkInfo) {
        queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
    }

我們可以看到在收到EVENT_NETWORK_INFO_CHANGED的message觸發(fā)了updateNetworkInfo這就是信號(hào)刷新的地方,
我們看到NetworkAgentInfo 就是從初始化的時(shí)候handleRegisterNetworkAgent函數(shù)中,HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos里面取出來(lái)的

case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
                    AsyncResult ar = (AsyncResult)msg.obj;
                    Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>)ar.result;
                    mDataRegState = drsRatPair.first;
                    if (mRilRat != drsRatPair.second) {
                        updateTcpBufferSizes(drsRatPair.second);
                    }
                    mRilRat = drsRatPair.second;
                    if (DBG) {
                        log("DcDefaultState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
                                + " drs=" + mDataRegState
                                + " mRilRat=" + mRilRat);
                    }
                    ServiceState ss = mPhone.getServiceState();
                    int networkType = ss.getDataNetworkType();
                    mNetworkInfo.setSubtype(networkType,
                            TelephonyManager.getNetworkTypeName(networkType));
                    if (mNetworkAgent != null) {
                        updateNetworkInfoSuspendState();
                        mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities());
                        mNetworkAgent.sendNetworkInfo(mNetworkInfo);
                        mNetworkAgent.sendLinkProperties(mLinkProperties);
                    }
                    break;

DataConenection.java 中刷新信號(hào)類(lèi)型的地方

class ConnectModeState extends State {
        @Override
        public void enter() {
            if (!mWifiNative.removeAllNetworks()) {
                loge("Failed to remove networks on entering connect mode");
            }
            mWifiInfo.reset();
            mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED);
            // Let the system know that wifi is available in client mode.
            setWifiState(WIFI_STATE_ENABLED);

            mNetworkInfo.setIsAvailable(true);
            if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo);
            ......................
        }

        @Override
        public void exit() {
            // Let the system know that wifi is not available since we are exiting client mode.
            mNetworkInfo.setIsAvailable(false);
            if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo);
            ......................
        }
}

WifiStateMachine信號(hào)類(lèi)型刷新的地方

好了,到這里framework信號(hào)類(lèi)型的初始化和更新就分析完畢了,中間過(guò)程雖然有點(diǎn)繁瑣,但總的來(lái)說(shuō)邏輯還是相對(duì)清晰的

下面簡(jiǎn)單總結(jié)下吧:

  • Systemui中顯示wifi和數(shù)據(jù)icon是根據(jù)ConnectivityService.java中上報(bào)的NetworkCapabilities狀態(tài)來(lái)定
    當(dāng)NetworkCapabilities getTransportTypes() 返回 TRANSPORT_CELLULAR(== 0)的時(shí)候就顯示數(shù)據(jù)信號(hào)
    而NetworkCapabilities getTransportTypes() 返回 TRANSPORT_WIFI(== 1)的時(shí)候就顯示wifi信號(hào)

  • framework信號(hào)類(lèi)型初始化的時(shí)候,每一個(gè)信號(hào)都對(duì)應(yīng)著一個(gè)NetworkAgent,WifiStateMachine 設(shè)置了TRANSPORT_WIFI,而DataConenection 設(shè)置了TRANSPORT_CELLULAR。

分析就到這里了,文章若有什么分析不對(duì)的地方,歡迎大家指正,謝謝O(∩_∩)O

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 如題,項(xiàng)目開(kāi)發(fā)或者Google Nexus等親兒子機(jī)器上,StatusBar經(jīng)常會(huì)看到wifi和sim icon顯...
    按捉老虎閱讀 2,928評(píng)論 0 4
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,030評(píng)論 2 59
  • 1、通過(guò)CocoaPods安裝項(xiàng)目名稱(chēng)項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明AI閱讀 16,211評(píng)論 3 119
  • 文章圖片上傳不正常,如需文檔,可聯(lián)系微信:1017429387 目錄 1 安裝... 4 1.1 配置探針... ...
    Mrhappy_a7eb閱讀 6,934評(píng)論 0 5
  • 2017.6.29 晨起感恩 我十分感恩大恩上師及諸佛菩薩的護(hù)佑和加持,感恩上師慈悲開(kāi)示十不善業(yè),給大家送來(lái)祝福...
    鵲曾閱讀 229評(píng)論 0 4

友情鏈接更多精彩內(nèi)容