1. 程式人生 > >ConnectivityManager and ConnectivityService --- Telephony data Part III

ConnectivityManager and ConnectivityService --- Telephony data Part III

ConnectivityManager and ConnectivityService

ConnectivityManager 和ConnectivityService的作用主要有五點:
1. 監聽網路連線(WiFi, GPRS, UMTS等)。

  通過NetworkAgent監聽網路連線的變化。NetworkAgent是bearer和ConnectivityService溝通的橋樑,
  bearer通過NetworkAgent將網路資訊更新到ConnectivityService中; ConnectivityService通過
  NetworkAgent給bearer傳送一些控制類的訊息等。

2. 當網路連線發生變化時傳送廣播通知監聽者。

傳送的廣播主要是ConnectivityManager.CONNECTIVITY_ACTION:android.net.conn.CONNECTIVITY_CHANGE

3. 當一個網路的連線斷開時,嘗試開啟另外一個網路連線。

當NetworkAgent斷開/去註冊的時候,會rematch network 和 network request,新的network會建立。

4. 為應用程式查詢可用網路狀態提供API,其中包括反饋詳細(fine-granted)/粗略(coarse-granted)資訊的API。

反饋資訊最詳細(fine-granted)的API是getAllNetworkState,而getAllNetworks,getActiveNetwork
相比較算是反饋資訊比較粗略的API。

5. 為需要資料業務的應用程式提供請求和選擇網路的API。

供應用程式請求網路連線的API是requestNetwork(...)系列,針對不同的應用需求,同名方法有六個。

NetworkFactory

每個bearer(cellular, wifi等)都會建立NetworkFactory用來接收ConnectivityService發出來的”scored NetworkRequests”, 所以NetworkFactory會有很多,比如TelephonyNetworkFactory, WifiNetworkFactory和PhoneSwitcher.PhoneSwitcherNetworkRequestListener等。

NetworkAgent

NetworkAgent是bearer(cellular,wifi)和ConnectivityService通訊的通道,所以會有很多的NetworkAgent,DataConnection.DcNetworkAgent和WifiStateMachine.WifiNetworkAgent等, NetworkAgent是和network對應的,所以如果一個bearer可以同時支援不同的network((IMS / Internet / MMS Apns on cellular, or perhaps connections with different SSID or P2P for Wi-Fi),那麼它可以擁有多個NetworkAgent。作為通訊通道,只有那些成功建立通道的NetworkAgent才會在ConnectivityService中儲存,那些斷開了通道的NetworkAgent會從ConnectivityService中刪掉。

下面說說cellular相關的NetworkFactory:

和Cellular相關的NetworkFactory有兩個 PhoneSwitcher.PhoneSwitcherNetworkRequestListener和TelephonyNetworkFactory(數量與slot/SIM 數量一致)。PhoneSwitcher構造了內部類PhoneSwitcherNetworkRequestListener(NetworkFactory子類)物件,並使用該物件在ConnectivityService中註冊了監聽,所以當ConnectivityService有網路請求(request/release)的時候PhoneSwitcher會收到訊息。PhoneSwitcher在內部有個ArrayList型別的變數mPrioritizedDcRequests用來儲存請求資訊,新請求會新增到mPrioritizedDcRequests,release的請求會從mPrioritizedDcRequests中刪除。PhoneSwitcher收到請求變化的訊息後會呼叫PhoneSwitcher.onEvaluate方法來判斷哪個phone需要active,哪個phone需要deactive, 並呼叫Ril.setDataAllowed方法通知modem,以及將新狀態通知到TelephonyNetworkFactory。
PhoneSwitcher.onEvaluate方法是如何來判斷哪個phone需要active/deactive的?PhoneSwitcher.onEvaluate會呼叫PhoneSwitcher.phoneIdForRequest方法對mPrioritizedDcRequests中的資料進行處理,mPrioritizedDcRequests中儲存的是DcRequest物件,後者包含了NetworkRequest物件,NetworkRequest中又包含了NetworkCapabilities物件,NetworkCapabilities中包含了StringNetworkSpecifier,StringNetworkSpecifier中包含了sub Id 資料,根據sub Id資料可以獲取對於的Phone Id; 如果沒有這些資料,那麼就使用預設資料SIM對應的Phone。

綜上,PhoneSwitcher會負責active/deactive 對應phone的資料功能。TelephonyNetworkFactory也在ConnectivityService中註冊了監聽,但是和PhoneSwitcher的作用不同,TelephonyNetworkFactory負責根據滿足條件的request去呼叫DcTracker.requestNetwork啟動切換/apn,並建立data connection。
PhoneSwitcher和TelephonyNetworkFactory都監聽了Subscription change和default data subscription change的事件:

PhoneSwitcher:

        try {
            tr.addOnSubscriptionsChangedListener("PhoneSwitcher", mSubscriptionsChangedListener);
        } catch (RemoteException e) {
        }

        mContext.registerReceiver(mDefaultDataChangedReceiver,
                new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));

TelephonyNetworkFactory:

        mSubscriptionMonitor.registerForSubscriptionChanged(mPhoneId, mInternalHandler,
                EVENT_SUBSCRIPTION_CHANGED, null);

        mIsDefault = false;
        mSubscriptionMonitor.registerForDefaultDataSubscriptionChanged(mPhoneId, mInternalHandler,
                EVENT_DEFAULT_SUBSCRIPTION_CHANGED, null);

當PhoneSwitcher收到訊息後會去deactive/active相應的phone的資料功能;TelephonyNetworkFactory會去release/request 資料連線。

PhoneSwitcher.PhoneSwitcherNetworkRequestListener和TelephonyNetworkFactory在向ConnectivityService註冊監聽之前都設定了各自的capability filter和score filter。它們的capability filter是一樣的,如下:

        NetworkCapabilities netCap = new NetworkCapabilities();
        netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);

TelephonyNetworkFactory的score filter是50; 而PhoneSwitcher.PhoneSwitcherNetworkRequestListener要收到所有的request,所以score filter是101。只有新request滿足了capability filter和score filter後,它們才會做處理。除了使用capability和score過濾request外還可以使用重寫(overridden)函式的方式,比如重寫startNetwork/stopNetwork,addNetworkRequest/removeNetworkRequest。


下面說說開機初始化過程中發生的小故事:

這部分主要講在開機初始化過程中,data connection建立之前,ConnectivityService、PhoneSwitcher以及TelephonyNetworkFactory之間程式碼流程,下方是一個流程圖:
這裡寫圖片描述
首先ConnectivityService的建構函式會建立一個預設的NetworkRequest物件(mDefaultRequest)。
PhoneSwitcher建立時會構造一個PhoneSwitcherNetworkRequestListener物件(NetworkFactory子類),然後用該物件在ConnectivityService中註冊監聽。ConnectivityService註冊監聽成功並通訊成功之後便會發送CMD_REQUEST_NETWORK(使用mDefaultRequest)訊息,經過一系列呼叫之後PhoneSwitcherNetworkRequestListener.needNetworkFor方法會被呼叫,該方法會發送一個EVENT_REQUEST_NETWORK,然後PhoneSwitcher.onRequestNetwork方法,PhoneSwitcher.onEvaluate和PhoneSwitcher.active方法相繼被呼叫。
TelephonyNetworkFactory的建構函式裡會呼叫PhoneSwitcher.registerForActivePhoneSwitch方法註冊監聽,PhoneSwitcher.active方法就會通知TelephonyNetworkFactory; TelephonyNetworkFactory註冊監聽時用的是EVENT_ACTIVE_PHONE_SWITCH,收到該訊息時被呼叫的方法是TelephonyNetworkFactory.onActivePhoneSwitch,經過流程圖中的一系列方法呼叫,適合network request的ApnContext會被設定成Enable狀態,這樣當需要的時候這個ApnContext便可以用於建立data connection。

TelephonyNetworkFactory能否呼叫DcTracker.requestNetwork去請求連線,要取決於PhoneSwitcher是否已經通過PhoneSwitcher.active方法通知了TelephonyNetworkFactory它所對應的卡可以連線網路。
對於單卡,這部分可能不重要; 但是對於雙卡,而新的網路連線請求所用的卡和當前資料卡不一致時,這部分邏輯完成 了對卡的選擇。

發彩信過程中使用mms APN的流程
發彩信需要使用MMS APN,MmsNetworkManager.acquireNetwork會呼叫ConnectivityManager.requesetNetwork方法請求網路連線,後面的流程和上面流程圖展示的很相似; network request會發送到TelephonyNetworkFactory中,TelephonyNetworkFactory會呼叫DcTracker.requestNetwork, 在這個方法中選擇合適的ApnContext(MMS),然後開始建立網路連線。
IMS apn是怎麼使用的?
IMS模組通過ConnectivityManger.requestNetwork(…)方法請求使用IMS apn建立data connection。


ConnectivityService是怎麼計算score的?
當有新的network requeset註冊或者NetworkAgent發生變化(註冊/去註冊、score發生變化、NetworkCapabilities改變和呼叫setAcceptUnvalidated/setAvoidUnvalidated設定針對unvalidated network的操作)時,rematchAllNetworksAndRequests/rematchNetworkAndRequests會被呼叫,一些network request會有新的score,而一些network可能會被斷開。

  1. 當有新的network requeset註冊時,對應的方法是handleRegisterNetworkRequest。
  2. 當有新的NetworkAgent註冊時,對應的方法是handleRegisterNetworkRequest。
  3. 當NetworkAgent去註冊時,對應的方法是handleAsyncChannelDisconnected。
  4. 當NetworkAgent的score發生變化時,對應的方法是updateNetworkScore。
  5. 當NetworkAgent的NetworkCapabilities發生變化時,對應的方法是updateCapabilities。
  6. 當setAcceptUnvalidated/setAvoidUnvalidated被呼叫,設定針對unvalidated network的操作時; 對應的方法是handleSetAcceptUnvalidated/handleSetAvoidUnvalidated。

rematchNetworkAndRequests(NetworkAgentInfo newNetwork, …)方法會遍歷所有的request判斷引數network是否是某個request的最合適的network,如果是,那麼將network的score更新request的score值,並通知NetworkFactory,NetworkFactory會根據score進行操作(release/request network)。
WiFi連線/斷開時,會有對應的NetworkAgent註冊/去註冊以及score更新,所有註冊的NetworkFactory都會收到訊息,TelephonyNetworkFactory收到訊息後會release當前的mobile network(cellular)。


結束!