1. 程式人生 > >Android -- 網路模組中NetworkFactory與NetworkAgent的通訊機制

Android -- 網路模組中NetworkFactory與NetworkAgent的通訊機制

Android -- NetworkFactory與NetworkAgent的通訊機制

轉自write.blog.csdn.net/postedit
在上一篇博文中講到,EthernetNetworkFactory包攬了Ethernet所有的網路管理操作,這其中就包含怎麼樣通知ConnectifyService(下文都簡稱CS)網路狀態發生變化。接下來,我們藉助有線網路來簡要介紹Android 4.4之後,網路模組是怎樣與CS通訊並進行網路管理的。 在啟動Ethernet網路服務時,我們會對Ethernet做一些初始化操作,以方便我們進行網路管理。看EthernetNetworkFactory::start()方法:
  1. /**
     
  2.      * Begin monitoring connectivity 
  3.      */
  4.     publicsynchronizedvoid start(Context context, Handler target) {  
  5.         // The services we use.
  6.         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);  
  7.         mNMService = INetworkManagementService.Stub.asInterface(b);  
  8.         mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);  
  9.         // Interface match regex.
  10.         mIfaceMatch = context.getResources().getString(  
  11.                 com.android.internal.R.string.config_ethernet_iface_regex);  
  12.         // Create and register our NetworkFactory.
  13.         mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());  
  14.         mFactory.setCapabilityFilter(mNetworkCapabilities);  
  15.         mFactory.setScoreFilter(-1); // this set high when we have an iface
  16.         mFactory.register();  
  17.         mContext = context;  
  18.         // Start tracking interface change events.
  19.         mInterfaceObserver = new InterfaceObserver();  
  20.         try {  
  21.             mNMService.registerObserver(mInterfaceObserver);  
  22.         } catch (RemoteException e) {  
  23.             Log.e(TAG, "Could not register InterfaceObserver " + e);  
  24.         }  
  25.         // If an Ethernet interface is already connected, start tracking that.
  26.         // Otherwise, the first Ethernet interface to appear will be tracked.
  27.         try {  
  28.             final String[] ifaces = mNMService.listInterfaces();  
  29.             for (String iface : ifaces) {  
  30.                 synchronized(this) {  
  31.                     if (maybeTrackInterface(iface)) {  
  32.                         // We have our interface. Track it.
  33.                         // Note: if the interface already has link (e.g., if we
  34.                         // crashed and got restarted while it was running),
  35.                         // we need to fake a link up notification so we start
  36.                         // configuring it. Since we're already holding the lock,
  37.                         // any real link up/down notification will only arrive
  38.                         // after we've done this.
  39.                         if (mNMService.getInterfaceConfig(iface).hasFlag("running")) {  
  40.                             updateInterfaceState(iface, true);  
  41.                         }  
  42.                         break;  
  43.                     }  
  44.                 }  
  45.             }  
  46.         } catch (RemoteException e) {  
  47.             Log.e(TAG, "Could not get list of interfaces " + e);  
  48.         }  
  49.     }  
start()方法接受一個Handler物件作為引數,該引數是在EthernetServiceImpl::start()中傳入的,它新建了一個HandlerThread物件,並傳入作為引數,從這可知網路管理的操作是執行在EthernetServiceImpl執行緒中的。 程式碼中建立了一個LocalNetworkFactory物件。LocalNetworkFactory繼承自NetworkFactory:
  1. /** 
  2.  * A NetworkFactory is an entity that creates NetworkAgent objects. 
  3.  * The bearers register with ConnectivityService using {@link #register} and 
  4.  * their factory will start receiving scored NetworkRequests.  NetworkRequests 
  5.  * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by 
  6.  * overridden function.  All of these can be dynamic - changing NetworkCapabilities 
  7.  * or score forces re-evaluation of all current requests. 
  8.  * 
  9.  * If any requests pass the filter some overrideable functions will be called. 
  10.  * If the bearer only cares about very simple start/stopNetwork callbacks, those 
  11.  * functions can be overridden.  If the bearer needs more interaction, it can 
  12.  * override addNetworkRequest and removeNetworkRequest which will give it each 
  13.  * request that passes their current filters. 
  14.  * @hide 
  15.  **/
  16. publicclass NetworkFactory extends Handler {  
  17. ...  
  18. public NetworkFactory(Looper looper, Context context, String logTag,  
  19.             NetworkCapabilities filter) {  
  20.         super(looper);  
  21.         LOG_TAG = logTag;  
  22.         mContext = context;  
  23.         mCapabilityFilter = filter;  
  24.     }  
  25. ...  
  26.     publicvoid register() {  
  27.         if (DBG) log("Registering NetworkFactory");  
  28.         if (mMessenger == null) {  
  29.             mMessenger = new Messenger(this);  
  30.             ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);  
  31.         }  
  32.     }  
  33. ...  
  34. // override to do simple mode (request independent)
  35.     protectedvoid startNetwork() { }  
  36.     protectedvoid stopNetwork() { }  
  37. ...  
  38. }  
NetworkFactory繼承自Handler,我們可以把它動作一個工廠,對網路的請求和終止操作都通過該物件進行處理。從註釋可知NetworkFactory與NetworkAgent物件有密切關係,它通過register()方法向CS進行註冊。start/stopNetwork()是提供的回撥函式 ,我們可以通過這兩個函式來請求或終止網路:
  1. publicvoid register() {  
  2.     if (DBG) log("Registering NetworkFactory");  
  3.     if (mMessenger == null) {  
  4.         mMessenger = new Messenger(this);  
  5.         ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);  
  6.     }  
  7. }  
建立NetworkFactory物件時,我們給它指定了一個特定執行緒的Looper物件;接著呼叫register()方法向CS註冊這個NetworkFactory物件,實際是呼叫CS中的registerNetworkFactory()方法:
  1. @Override
  2. publicvoid registerNetworkFactory(Messenger messenger, String name) {  
  3.     enforceConnectivityInternalPermission();  
  4.     NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());  
  5.     mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));  
  6. }  
引數Messenger物件是一個可以跨程序傳遞的例項物件,它實際代表一個Handler物件,我們可以像使用Handler物件一樣,使用Messenger物件來發送訊息;此處該引用指向mNetworkFactory這個Handler物件,它繫結的Looper屬於一個特定的執行緒,它在EthernetServiceImpl中建立。看NetworkFactoryInfo,它是一個CS中的內部類,儲存了特定的Messager物件和一個與之關聯的AsyncChannel物件。看到此處我們知道這裡會通過非同步通道來進行訊息傳遞的。接著會發送一個EVENT_REGISTER_NETWORK_FACTORY訊息,它被CS中的InternalHandler處理,這個Handler主要完成CS內部訊息事件的處理。我們直接看處理過程:
  1. case EVENT_REGISTER_NETWORK_FACTORY: {  
  2.                     handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);  
  3.                     break;  
  4.                 }  
  1. privatevoid handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {  
  2.     if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);  
  3.     mNetworkFactoryInfos.put(nfi.messenger, nfi);  
  4.     nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);  
  5. }  
非同步通道的內容在以前的博文中已經講過。先將之前建立的nfi物件以Messenger物件為key新增到mNetworkFactoryInfos中,它是一個HashMap物件,方便後面獲取。再呼叫connect()方法進行AsyncChannel連線的建立:
  1. /** 
  2.      * Connect handler and messenger. 
  3.      * 
  4.      * Sends a CMD_CHANNEL_HALF_CONNECTED message to srcHandler when complete. 
  5.      *      msg.arg1 = status 
  6.      *      msg.obj = the AsyncChannel 
  7.      * 
  8.      * @param srcContext 
  9.      * @param srcHandler 
  10.      * @param dstMessenger 
  11.      */
  12.     publicvoid connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {  
  13.         if (DBG) log("connect srcHandler to the dstMessenger  E");  
  14.         // We are connected
  15.         connected(srcContext, srcHandler, dstMessenger);  
  16.         // Tell source we are half connected
  17.         replyHalfConnected(STATUS_SUCCESSFUL);  
  18.         if (DBG) log("connect srcHandler to the dstMessenger X");  
  19.     }  
  1. /** 
  2.  * Connect handler to messenger. This method is typically called 
  3.  * when a server receives a CMD_CHANNEL_FULL_CONNECTION request 
  4.  * and initializes the internal instance variables to allow communication 
  5.  * with the dstMessenger. 
  6.  * 
  7.  * @param srcContext 
  8.  * @param srcHandler 
  9.  * @param dstMessenger 
  10.  */
  11. publicvoid connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {  
  12.     if (DBG) log("connected srcHandler to the dstMessenger  E");  
  13.     // Initialize source fields
  14.     mSrcContext = srcContext;  
  15.     mSrcHandler = srcHandler;  
  16.     mSrcMessenger = new Messenger(mSrcHandler);  
  17.     // Initialize destination fields
  18.     mDstMessenger = dstMessenger;  
  19.     if (DBG) log("connected srcHandler to the dstMessenger X");  
  20. }  
要明確的是,srcHandler指向CS中的NetworkStateTrackerHandler物件,它主要負責接收網路模組傳送的訊息,並進行網路更新;mSrcMessenger是代表該Handler物件的一個引用;mDstMessenger則代表EthernetNetworkFactory中的LocalNetworkFactory物件,該物件也是一個Handler。然後向mSrcHandler回覆CMD_CHANNEL_HALF_CONNECTED訊息:
  1. /** 
  2.     * Reply to the src handler that we're half connected. 
  3.     * see: CMD_CHANNEL_HALF_CONNECTED for message contents 
  4.     * 
  5.     * @param status to be stored in msg.arg1 
  6.     */
  7.    privatevoid replyHalfConnected(int status) {  
  8.        Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);  
  9.        msg.arg1 = status;  
  10.        msg.obj = this;  
  11.        msg.replyTo = mDstMessenger;  
  12.        /* 
  13.         * Link to death only when bindService isn't used. 
  14.         */
  15.        if (mConnection == null) {  
  16.            mDeathMonitor = new DeathMonitor();  
  17.            try {  
  18.                mDstMessenger.getBinder().linkToDeath(mDeathMonitor, 0);//為了防止AsyncChannel用於不同程序通訊時,若Server端所在的程序已經死掉,來通知
  19.                                                                     //Client端程序進行一些後期處理
  20.            } catch (RemoteException e) {  
  21.                mDeathMonitor = null;  
  22.                // Override status to indicate failure
  23.                msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;  
  24.            }  
  25.        }  
  26.        mSrcHandler.sendMessage(msg);  
  27.    }  
CS中是這樣處理的:
  1. case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {  
  2.                     handleAsyncChannelHalfConnect(msg);  
  3.                     break;  
  4.                 }  
  1. privatevoid handleAsyncChannelHalfConnect(Message msg) {  
  2.         AsyncChannel ac = (AsyncChannel) msg.obj;  
  3.         if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {  
  4.             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {  
  5.                 if (VDBG) log("NetworkFactory connected");  
  6.                 // A network factory has connected.  Send it all current NetworkRequests.
  7.                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {  
  8.                     if (nri.isRequest == falsecontinue;  
  9.                     NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);  
  10.                     ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,  
  11.                             (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);  
  12.                 }  
  13.             } else {  
  14.                 loge("Error connecting NetworkFactory");  
  15.                 mNetworkFactoryInfos.remove(msg.obj);  
  16.             }  
  17.         } elseif (mNetworkAgentInfos.containsKey(msg.replyTo)) {  
  18.             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {  
  19.                 if (VDBG) log("NetworkAgent connected");  
  20.                 // A network agent has requested a connection.  Establish the connection.
  21.                 mNetworkAgentInfos.get(msg.replyTo).asyncChannel.  
  22.                         sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);  
  23.             } else {  
  24.                 loge("Error connecting NetworkAgent");  
  25.                 NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);  
  26.                 if (nai != null) {  
  27.                     finalboolean wasDefault = isDefaultNetwork(nai);  
  28.                     synchronized (mNetworkForNetId) {  
  29.                         mNetworkForNetId.remove(nai.network.netId);  
  30.                         mNetIdInUse.delete(nai.network.netId);  
  31.                     }  
  32.                     // Just in case.
  33.                     mLegacyTypeTracker.remove(nai, wasDefault);  
  34.                 }  
  35.             }  
  36.         }  
  37.     }  
我們先前已經向mNetworkFactoryInfos集合新增過NetworkFactoryInfo物件,實際的處理是:
  1. // A network factory has connected.  Send it all current NetworkRequests.
  2.                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {  
  3.                     if (nri.isRequest == falsecontinue;  
  4.                     NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);  
  5.                     ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,  
  6.                             (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);  
  7.                 }  
直接看訊息傳送處理;通過AsyncChannel物件向mDstMessenger物件傳送訊息。根據前面所述,即向Ethernet中的LocalNetworkFactory傳送CMD_REQUEST_NETWORK訊息,表示當前系統要請求一個網路。有前面可知父類NetworkFactory本身就是一個Handler,它處理該訊息:
  1. @Override
  2. publicvoid handleMessage(Message msg) {  
  3.     switch (msg.what) {  
  4.         case CMD_REQUEST_NETWORK: {  
  5.             handleAddRequest((NetworkRequest)msg.obj, msg.arg1);  
  6.             break;  
  7.         }  
  8.         case CMD_CANCEL_REQUEST: {  
  9.             handleRemoveRequest((NetworkRequest) msg.obj);  
  10.             break;  
  11.         }  
  12.         case CMD_SET_SCORE: {  
  13.             handleSetScore(msg.arg1);  
  14.             break;  
  15.         }  
  16.         case CMD_SET_FILTER: {  
  17.             handleSetFilter((NetworkCapabilities) msg.obj);  
  18.             break;  
  19.         }  
  20.     }  
  21. }  
  1. privatevoid handleAddRequest(NetworkRequest request, int score) {  
  2.         NetworkRequestInfo n = mNetworkRequests.get(request.requestId);  
  3.         if (n == null) {  
  4.             if (DBG) log("got request " + request + " with score " + score);  
  5.             n = new NetworkRequestInfo(request, score);  
  6.             mNetworkRequests.put(n.request.requestId, n);  
  7.         } else {  
  8.             if (VDBG) log("new score " + score + " for exisiting request " + request);  
  9.             n.score = score;  
  10.         }  
  11.         if (VDBG) log("  my score=" + mScore + ", my filter=" + mCapabilityFilter);  
  12.         evalRequest(n);  
  13.     }  
  1. privatevoid evalRequest(NetworkRequestInfo n) {  
  2.         if (VDBG) log("evalRequest");  
  3.         if (n.requested == false && n.score < mScore &&  
  4.                 n.request.networkCapabilities.satisfiedByNetworkCapabilities(  
  5.                 mCapabilityFilter) && acceptRequest(n.request, n.score)) {  
  6.             if (VDBG) log("  needNetworkFor");  
  7.             needNetworkFor(n.request, n.score);  
  8.             n.requested = true;  
  9.         } elseif (n.requested == true &&  
  10.                 (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(  
  11.                 mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {  
  12.             if (VDBG) log("  releaseNetworkFor");  
  13.             releaseNetworkFor(n.request);  
  14.             n.requested = false;  
  15.         } else {  
  16.             if (VDBG) log("  done");  
  17.         }  
  18.     }  
如果訊息附帶的NetworkRequestInfo物件沒有儲存,則先儲存到mNetworkRequests集合中,同時根據NetworkRequestInfo物件中的requested和score屬性值,相應的呼叫needNetworkFor()或releaseNetworkFor():
  1. // override to do fancier stuff
  2. protectedvoid needNetworkFor(NetworkRequest networkRequest, int score) {  
  3.     if (++mRefCount == 1) startNetwork();  
  4. }  
  5. protectedvoid releaseNetworkFor(NetworkRequest networkRequest) {  
  6.     if (--mRefCount == 0) stopNetwork();  
  7. }  
即呼叫LocalNetworkFactory中的start/stopNetwork()來管理網路的開啟和關閉:
  1. privateclass LocalNetworkFactory extends NetworkFactory {  
  2.     LocalNetworkFactory(String name, Context context, Looper looper) {  
  3.         super(looper, context, name, new NetworkCapabilities());  
  4.     }  
  5.     protectedvoid startNetwork() {  
  6.         onRequestNetwork();  
  7.     }  
  8.     protectedvoid stopNetwork() {  
  9.     }  
  10. }  
onRequestNetwork()處理Ethernet的連線操作,包括對靜態IP和DHCP的處理。到這裡,一個NetworkFactory物件的註冊過程就結束了。 我們看onRequestNetwork()方法來觸發一個網路的連線:
  1. /* Called by the NetworkFactory on the handler thread. */
  2. publicvoid onRequestNetwork() {  
  3.     // TODO: Handle DHCP renew.
  4.     Thread dhcpThread = new Thread(new Runnable() {  
  5.         publicvoid run() {  
  6.             if (DBG) Log.i(TAG, "dhcpThread(" + mIface + "): mNetworkInfo=" + mNetworkInfo);  
  7.             LinkProperties linkProperties;  
  8.             IpConfiguration config = mEthernetManager.getConfiguration();  
  9.             if (config.getIpAssignment() == IpAssignment.STATIC) {  
  10.                 if (!setStaticIpAddress(config.getStaticIpConfiguration())) {  
  11.                     // We've already logged an error.
  12.                     return;  
  13.                 }  
  14.                 linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);  
  15.             } else {  
  16.                 mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);  
  17.                 DhcpResults dhcpResults = new DhcpResults();  
  18.                 // TODO: Handle DHCP renewals better.
  19.                 // In general runDhcp handles DHCP renewals for us, because
  20.                 // the dhcp client stays running, but if the renewal fails,
  21.                 // we will lose our IP address and connectivity without
  22.                 // noticing.
  23.                 if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {  
  24.                     Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());  
  25.                     // set our score lower than any network could go
  26.                     // so we get dropped.
  27.                     mFactory.setScoreFilter(-1);  
  28.                     // If DHCP timed out (as opposed to failing), the DHCP client will still be
  29.                     // running, because in M we changed its timeout to infinite. Stop it now.
  30.                     NetworkUtils.stopDhcp(mIface);  
  31.                     return;  
  32.                 }  
  33.                 linkProperties = dhcpResults.toLinkProperties(mIface);  
  34.             }  
  35.            ...  
  36.         }  
  37.     });  
  38.     dhcpThread.start();  
  39. }  
CS中處理網路更新的Handler是NetworkStateTrackerHandler。當網路連線後,通知CS更新網路的操作則是通過NetworkAgent物件進行的。從它的定義可知,它也是一個Handler:
  1. synchronized(EthernetNetworkFactory.this) {  
  2.     if (mNetworkAgent != null) {  
  3.         Log.e(TAG, "Already have a NetworkAgent - aborting new request");  
  4.         return;  
  5.     }  
  6.     mLinkProperties = linkProperties;  
  7.     mNetworkInfo.setIsAvailable(true);  
  8.     mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);  
  9.     // Create our NetworkAgent.
  10.     mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,  
  11.             NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,  
  12.             NETWORK_SCORE) {  
  13.         publicvoid unwanted() {  
  14.             synchronized(EthernetNetworkFactory.this) {  
  15.                 if (this == mNetworkAgent) {  
  16.                     NetworkUtils.stopDhcp(mIface);  
  17.                     mLinkProperties.clear();  
  18.                     mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null,  
  19.                             mHwAddr);  
  20.                     updateAgent();  
  21.                     mNetworkAgent = null;  
  22.                     try {  
  23.                         mNMService.clearInterfaceAddresses(mIface);  
  24.                     } catch (Exception e) {  
  25.                         Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);  
  26.                     }  
  27.                 } else {  
  28.                     Log.d(TAG, "Ignoring unwanted as we have a more modern " +  
  29.                             "instance");  
  30.                 }  
  31.             }  
  32.         };  
  33.     };  
  34. }  
  1. /** 
  2.      * Called when ConnectivityService has indicated they no longer want this network. 
  3.      * The parent factory should (previously) have received indication of the change 
  4.      * as well, either canceling NetworkRequests or altering their score such that this 
  5.      * network won't be immediately requested again. 
  6.      */
  7.     abstractprotectedvoid unwanted();  
重寫的unwanted()方法則在CS指出不再需要當前網路連線時呼叫。除了清除掉網路配置資訊,還會把mNetworkAgent置為null。從程式碼中可以看出,mNetworkAgent是否為null標誌了當前是否該型別的網路連線正在使用,如果有則不會處理新的網路請求。 既然網路狀態的變化是由NetworkAgent處理的,那我們就接著看NetworkAgent是怎麼跟CS通訊的:
  1. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,  
  2.             NetworkCapabilities nc, LinkProperties lp, int score) {  
  3.         this(looper, context, logTag, ni, nc, lp, score, null);  
  4.     }  
  5.     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,  
  6.             NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {  
  7.         super(looper);  
  8.         LOG_TAG = logTag;  
  9.         mContext = context;  
  10.         if (ni == null || nc == null || lp == null) {  
  11.             thrownew IllegalArgumentException();  
  12.         }  
  13.         if (VDBG) log("Registering NetworkAgent");  
  14.         ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(  
  15.                 Context.CONNECTIVITY_SERVICE);  
  16.         netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),  
  17.                 new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);  
  18.     }  
在建立NetworkAgent物件時,接受一個特定的Looper物件,並向CS註冊該NetworkAgent物件,這與LocalNetworkFactory的處理類似。看CS中具體的註冊處理:
  1. publicint registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,  
  2.            LinkProperties linkProperties, NetworkCapabilities networkCapabilities,  
  3.            int currentScore, NetworkMisc networkMisc) {  
  4.        enforceConnectivityInternalPermission();  
  5.        // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
  6.        // satisfies mDefaultRequest.
  7.        final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),  
  8.                new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(  
  9.                linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,  
  10.                mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);  
  11.        synchronized (this) {  
  12.            nai.networkMonitor.systemReady = mSystemReady;  
  13.        }  
  14.        addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network);  
  15.        if (DBG) log("registerNetworkAgent " + nai);  
  16.        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));  
  17.        return nai.network.netId;  
  18.    }  
這裡的Messager物件是NetworkAgent物件自身的一個引用,建立對應的NetworkAgentInfo物件,其內部建立了一個AsyncChannel物件;messenger引數前面介紹過,mTrackderHandler是NetworkStateTrackerHandler的一個例項。向InternalHandler傳送EVENT_REGISTER_NETWORK_AGENT訊息,處理註冊操作。看CS中的處理:
  1. case EVENT_REGISTER_NETWORK_AGENT: {  
  2.                     handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);  
  3.                     break;  
  4.                 }  
  1. privatevoid handleRegisterNetworkAgent(NetworkAgentInfo na) {  
  2.         if (VDBG) log("Got NetworkAgent Messenger");  
  3.         mNetworkAgentInfos.put(na.messenger, na);  
  4.         synchronized (mNetworkForNetId) {  
  5.             mNetworkForNetId.put(na.network.netId, na);  
  6.         }  
  7.         na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);  
  8.         NetworkInfo networkInfo = na.networkInfo;  
  9.         na.networkInfo = null;  
  10.         updateNetworkInfo(na, networkInfo);//更新網路狀態的函式
  11.     }  
也是將na和messenger物件儲存到一個HashMap集合中,也是通過AsyncChannel進行通訊,也是呼叫connect()進行連線,這跟前面所述的NetworkFactory的處理基本類似。從前面的分析可知這個AsyncChannel物件中,mSrcHandler和mSrcMessenger指向一個CS中的NetworkStateTrackerHandler,mDstMessenger指向要註冊的NetworkAgent物件,因為它本身也是個Handler。接著向mSrcHandler傳送CMD_CHANNEL_HALF_CONNECTED訊息,同樣也是handleAsyncChannelHalfConnect()處理,只不過走的處理分支不同,有前面的介紹可知:
  1. if (VDBG) log("NetworkAgent connected");  
  2.                 // A network agent has requested a connection.  Establish the connection.
  3.                 mNetworkAgentInfos.get(msg.replyTo).asyncChannel.  
  4.                         sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);  
使用AsyncChannel向mDstMessenger傳送CMD_CHANNEL_FULL_CONNECTION訊息,即向NetworkAgent物件傳送該訊息:
  1. case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {  
  2.                 if (mAsyncChannel != null) {  
  3.                     log("Received new connection while already connected!");  
  4.                 } else {  
  5.                     if (VDBG) log("NetworkAgent fully connected");  
  6.                     AsyncChannel ac = new AsyncChannel();  
  7.                     ac.connected(nullthis, msg.replyTo);  
  8.                     ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,  
  9.                             AsyncChannel.STATUS_SUCCESSFUL);  
  10.                     synchronized (mPreConnectedQueue) {  
  11.                         mAsyncChannel = ac;  
  12.                         for (Message m : mPreConnectedQueue) {  
  13.                             ac.sendMessage(m);  
  14.                         }  
  15.                         mPreConnectedQueue.clear();  
  16.                     }  
  17.                 }  
  18.                 break;  
  19.             }  
如果當前NetworkAgent是第一次進行連線,mAsyncChannel為null;新建一個AsyncChannel物件,呼叫connected()進行FULL_CONNECTION:
  1. publicvoid connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {  
  2.         if (DBG) log("connected srcHandler to the dstMessenger  E");  
  3.         // Initialize source fields
  4.         mSrcContext = srcContext;  
  5.         mSrcHandler = srcHandler;  
  6.         mSrcMessenger = new Messenger(mSrcHandler);  
  7.         // Initialize destination fields
  8.         mDstMessenger = dstMessenger;  
  9.         if (DBG) log("connected srcHandler to the dstMessenger X");  
  10.     }  
mSrcHandler和mSrcMessenger指向當前的NetworkAgent物件;mDstMessenger指向CS中的NetworkStateTrackerHandler物件。隨後再發送CMD_CHANNEL_FULLY_CONNECTED訊息,表示整個AsyncChannel的連線成功,可以進行通訊了。同時,還會遍歷mPreConnectedQueue集合,這個集合中儲存了當mAsyncChannel為null時的所有與更新網路資訊相關的message,通過ac.sendMessage()向CS傳送所有的message進行狀態更新(要注意,ac物件的mSrcHanlder為當前NetworkAgent,mDstMessenger指向NetworkStateTrackerHandler)。 至此可知,我們通過NetworkAgent向CS報告網路的變化,通知它進行網路狀態的更新。EthernetNetworkFactory中通過updateAgent()完成此項工作:
  1. publicvoid updateAgent() {  
  2.     synchronized (EthernetNetworkFactory.this) {  
  3.         if (mNetworkAgent == nullreturn;  
  4.         if (DBG) {  
  5.             Log.i(TAG, "Updating mNetworkAgent with: " +  
  6.                   mNetworkCapabilities + ", " +  
  7.                   mNetworkInfo + ", " +  
  8.                   mLinkProperties);  
  9.         }  
  10.         mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);  
  11. 相關推薦

    Android -- 網路模組NetworkFactoryNetworkAgent通訊機制

    Android -- NetworkFactory與NetworkAgent的通訊機制 轉自write.blog.csdn.net/postedit 在上一篇博文中講到,EthernetNetworkFactory包攬了Ethernet所有的網路管理操作,這其中就包含怎麼樣通知ConnectifyServi

    socket網路程式設計伺服器客戶端通訊失敗的問題

    伺服器程式碼如下 public class server { public static void main(String[] args) throws IOException { ServerSocket server=new S

    Android網路程式設計的URLConnection的IP設定

    虛擬機器測試:10.0.0.2 PC連線乙太網:通過cmd命令,進入命令視窗。輸入ipconfig檢視乙太網介面卡ipv4地址 Android測試機連入本機WiFi網路:如圖 如果Android上提示 java.net.SocketTimeoutEx

    WPFMainWindowPage通訊

    與WinForm不同,WPF拋棄了MDIwindow的概念,因為微軟的工程師們相信主視窗加可以切換的Page,也就象是標籤頁似的結構,才更符合人們使用的習慣。剛好前一階段需要設計一個軟體介面,需要實現不同功能介面的切換功能,我用了MainWindow->F

    網路程式設計阻塞非阻塞、同步非同步、I/O模型的理解

    1. 概念理解      在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unblock)四種呼叫方式:同步:所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。也就是必須一件一件事做,等前一件做完了才能做下一件事。 例如

    Android網路程式設計關於AsyncHttpClient獲取cookie的問題

    之前的專案登入模組存在問題,登入狀態和使用者名稱直接存在了SharedPreferences裡,進入軟體時直接判斷使用者名稱是否為空,為空時才進入登入頁面,否則直接讀取SP中的相關資料,看了AsyncHttpClient的文件後,才發現可以允許讀取cookie。

    android網路程式設計使用java的回撥機制

    1) 先定義一個介面 public interface HttpCallbackListener { void onFinish(String response); void onError(Exception e); } 2) 在工具類HttpUtil中

    Android網路傳輸必用的兩個加密演算法:MD5 和 RSA (附java完成測試程式碼)

    MD5和RSA是網路傳輸中最常用的兩個演算法,瞭解這兩個演算法原理後就能大致知道加密是怎麼一回事了。但這兩種演算法使用環境有差異,剛好互補。一、MD5演算法首先MD5是不可逆的,只能加密而不能解密。比如明文是yanzi1225627,得到MD5加密後的字串是:14F2AE15

    Windows網路程式設計SocketWSASocket區別

    這2個函式的主要功能都是建立一個SOCKET,函式定義分別如下: SOCKET WSAAPI socket( _In_ int af, _In_ int type, _In_ int pr

    納稅服務投訴受理模組投訴回覆的級聯查詢等細節

    1、投訴和投訴回覆實體及hbm配置檔案 Complain.java package cn.buaa.nsfw.complain.entity; import java.sql.Timestamp; import java.util.HashMap; import jav

    Android網路程式設計(使用socket進行通訊

          Socket就是網路套接字程式設計,網路程式設計簡單的理解就是兩臺計算機相互通訊資料而已。對於程式設計師而言,去掌握一種程式設計介面並使用一種程式設計模型相對就會顯得簡單的多了.Java SDK提供一些相對簡單的Api來完成這些工作,這些Api存在與java.n

    Android每天一個知識點+Demo—跨程序通訊機制AIDL入門

    一 Why-為什麼要用AIDL 沙箱理念:在Android中,每個應用(Application)程式都執行在獨立的程序中,無法直接呼叫到其他應用的資源。當一個應用被執行時,一些操作是被限制的,比如訪問記憶體,訪問感測器等等。 好處:這也保證了當其中一個程式出現異常而不會影

    Android安全/開發基礎--6--程序間通訊機制(IPC)

    6-1、多程序 1、多程序分為兩種: 第一種情況是一個應用因為某些原因自身需要採用多執行緒模式來實現。 另一種情況是當前應用需要向其他應用獲取資料。 2、Android中的多程序模式: 通過給四大元件指定android:process屬性,可以開啟多程序模式,使

    Android進階:網路資料儲存—步驟1:Android網路通訊(第2小節:Handler)

    內容概覽 Handler是什麼 為什麼要使用Handler Handler/Looper/MessageQueue/Message Handler如何去實現(三種實現:1、下載檔案並更新進度條 2、倒計時 3、打地鼠的遊戲實現) 工作原理 如果更好的使用 擴充套

    Android進階:網路資料儲存—步驟1:Android網路通訊(第3小節:ListView上)

    內容概要: 一、課程介紹 二、ListView的準備工作 ListView簡介 ListView的實現步驟 三、ListView簡單應用 Adapter的資料繫結 最簡單ListView效果演示 獲取系統已安裝應用列表 優化效能 一、課程介紹 什麼是List

    Android進階:網路資料儲存—步驟1:Android網路通訊(第4小節:ListView下)

    內容概括: 一、網路下載資料並顯示在ListView上 使用非同步訪問網路 解析獲取的Json資料 載入資料到ListView上 二、不同item的引用 引用不同行佈局 一、網路下載資料並顯示在ListView上 1.1-使用非同步訪問網路 //非同步訪問網路

    Android進階:網路資料儲存—步驟1:Android網路通訊(第6小節:GridView)

    內容概要: GirdView(網格檢視)顯示本地資料 GirdView屬性簡介 案例一:用GirdView展示文字 案例二:用GridView顯示已安裝應用 GridView顯示網路 用GridView載入網路圖片(上) 用GridView載入網路圖片(下) 一、

    Android進階:網路資料儲存—步驟1:Android網路通訊(第7小節:CadView)

    內容概要: CardView基礎 CardView介紹 CardVie常用屬性 CardView屬性效果展示 CardView案例實現 CardVie基本操作 案例-佈局搭建 案例-實體類建立 案例-功能實現 案例-適配 CardView開發注意事項 一、Ca

    node.jsnet網路模組TCP服務端客戶端的使用

    node.js中net模組為我們提供了TCP伺服器和客戶端通訊的各種介面。   一、建立伺服器並監聽埠 const net = require('net'); //建立一個tcp服務 //引數一表示建立服務的一些配置 //引數二表示 事件 'connection' 監聽回撥函式

    androidfragmentactivity之間通訊原理以及例子

    首先,如果你想在android3.0及以下版本使用fragment,你必須引用android-support-v4.jar這個包 然後你寫的activity不能再繼承自Activity類了,而是要繼承android.support.v4.app.FragmentA