網路連線評分機制之NetworkAgent
阿新 • • 發佈:2019-01-17
http://blog.csdn.net/u010961631/article/details/48971651
前面介紹了開機過程中各個網路提供者的初始化過程,其實就是建立自己的NetworkFactory,並將其註冊到ConnectivityService。而在介紹NetworkFactory的時候,我們看到該類的官方註釋中有這麼一句描述:
- "A NetworkFactory is an entity that creates NetworkAgent objects."
我們接下來介紹NetworkAgent。
一、NetworkAgent介紹
其實在上一個文件《Framework中的連線管理機制》中已經介紹過NetworkAgent相關知識了,現在我們來從另一個角度分析一下該物件的作用。從剛才NetworkFactory的註釋我們知道,NetworkAgent是被NetworkFactory建立的,這裡的建立並不是說在NetworkFactory內部建立NetworkAgent,而是說,在NetworkFactory這個環境就緒之後,網路提供者才可以建立NetworkAgent。並且在一個NetworkFactory中可以建立不同的NetworkAgent,他們擁有不同的Capabilities等引數。
而他們之間還有一個區別就是,NetworkFactory是在系統初始化時就被建立,而NetworkAgent是在真正接入網路時才會建立。
我們用運營商之間的關係來比喻他們的關係。
NetworkFactory相當於不同的運營商,比如中國電信、鐵通、移動,他們具備聯通網際網路的能力,當用戶入網時就決定了自己的運營商(即完成NetworkFactory初始化)。但同時在每個運營商內部又建立各個不同的接入點,比如對於中國電信來說,還分為上海電信、河北電信等,只有當用戶開啟電腦真正上網的時候,才會被分配具體的接入點(即完成NetworkAgent初始化)。
也就是說,同一個NetworkFactory可以在不同的時刻根據需要建立不同的NetworkAgent,比如使用資料上網時,會根據當前的需要(傳送MMS還是IMS,或者單純上網)來建立不同引數的NetworkAgent(不同的APN引數)物件,然後將其註冊到ConnectivityService中。
下面我們跟蹤一下資料連線的建立過程來看一下NetworkAgent的使用。
二、NetworkAgent建立過程
當資料連線建立成功時,就會在DataConnection中進入DcActiveState的狀態機,然後就會建立資料連線的NetworkAgent物件:- @DataConnection.java
- privateclass DcActiveState extends State {
- @Overridepublicvoid enter() {
- mRetryManager.restoreCurMaxRetryCount();
- mDcController.addActiveDcByCid(DataConnection.this);
- //更新當前的NetworkInfo狀態
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, mNetworkInfo.getReason(), null);
- mNetworkInfo.setExtraInfo(mApnSetting.apn);
- updateTcpBufferSizes(mRilRat);
- //資料建立成功,建立並註冊NetworkAgent
- mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
- "DcNetworkAgent", mNetworkInfo, makeNetworkCapabilities(), mLinkProperties,
- 50);
- }
- }
下面我們來看NetworkAgent的建立過程:
- @NetworkAgent.java
- 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) {
- thrownew IllegalArgumentException();
- }
- ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);
- cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
- }
然後我們繼續來看在ConnectivityService中的註冊過程:
- @ConnectivityService.java
- publicvoid registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkMisc networkMisc) {
- //許可權檢查
- enforceConnectivityInternalPermission();
- NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
- new NetworkInfo(networkInfo), new LinkProperties(linkProperties),
- new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler,
- new NetworkMisc(networkMisc));
- synchronized (this) {
- nai.networkMonitor.systemReady = mSystemReady;
- }
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
- }
然後就把當前建立的NetworkAgentInfo物件放入EVENT_REGISTER_NETWORK_AGENT訊息中,傳送給Handler處理:
- @ConnectivityService.java
- privateclass InternalHandler extends Handler {
- publicvoid handleMessage(Message msg) {
- NetworkInfo info;
- switch (msg.what) {
- case EVENT_REGISTER_NETWORK_AGENT: {
- handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
- break;
- }
- }
- }
- }
- privatevoid handleRegisterNetworkAgent(NetworkAgentInfo na) {
- //將NetworkAgentInfo放入mNetworkAgentInfos中
- mNetworkAgentInfos.put(na.messenger, na);
- assignNextNetId(na);
- //發起連線請求
- na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
- NetworkInfo networkInfo = na.networkInfo;
- na.networkInfo = null;
- //更新最新的NetworkInfo
- updateNetworkInfo(na, networkInfo);
- }
1、將新註冊的NetworkAgentInfo儲存到mNetworkAgentInfos中;
2、利用剛才建立的AsyncChannel向NetworkAgent發起單向連線請求;
3、更新最新的NetworkAgentInfo狀態;
我們主要關注第二個過程,而第三個過程將會在接下來小節中介紹。
根據AsyncChannel的原理(不懂的點這裡),此時ConnectivityService發起的是單向的AsyncChannel連線,發起後將會在mTrackerHandler中收到CMD_CHANNEL_HALF_CONNECTED的訊息:
- @ConnectivityService.java
- privateclass NetworkStateTrackerHandler extends Handler {
- publicvoid handleMessage(Message msg) {
- NetworkInfo info;
- switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
- handleAsyncChannelHalfConnect(msg);
- break;
- }
- }
- }
- }
- privatevoid handleAsyncChannelHalfConnect(Message msg) {
- AsyncChannel ac = (AsyncChannel) msg.obj;
- if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
- } elseif (mNetworkAgentInfos.containsKey(msg.replyTo)) {
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- //向NetworkAgent發起雙向連線請求
- mNetworkAgentInfos.get(msg.replyTo).asyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
- } else {
- }
- }
- }