Android -- 网络模块中NetworkFactory与NetworkAgent的通信机制

来源:互联网 发布:网络电视机如何使用 编辑:程序博客网 时间:2024/06/15 20:15

Android -- NetworkFactory与NetworkAgent的通信机制

转自write.blog.csdn.net/postedit
在上一篇博文中讲到,EthernetNetworkFactory包揽了Ethernet所有的网络管理操作,这其中就包含怎么样通知ConnectifyService(下文都简称CS)网络状态发生变化。接下来,我们借助有线网络来简要介绍Android 4.4之后,网络模块是怎样与CS通信并进行网络管理的。
在启动Ethernet网络服务时,我们会对Ethernet做一些初始化操作,以方便我们进行网络管理。看EthernetNetworkFactory::start()方法:
[java] view plain copy
  1. /** 
  2.      * Begin monitoring connectivity 
  3.      */  
  4.     public synchronized void 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.   
  10.         // Interface match regex.  
  11.         mIfaceMatch = context.getResources().getString(  
  12.                 com.android.internal.R.string.config_ethernet_iface_regex);  
  13.   
  14.         // Create and register our NetworkFactory.  
  15.         mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());  
  16.         mFactory.setCapabilityFilter(mNetworkCapabilities);  
  17.         mFactory.setScoreFilter(-1); // this set high when we have an iface  
  18.         mFactory.register();  
  19.   
  20.         mContext = context;  
  21.   
  22.         // Start tracking interface change events.  
  23.         mInterfaceObserver = new InterfaceObserver();  
  24.         try {  
  25.             mNMService.registerObserver(mInterfaceObserver);  
  26.         } catch (RemoteException e) {  
  27.             Log.e(TAG, "Could not register InterfaceObserver " + e);  
  28.         }  
  29.   
  30.         // If an Ethernet interface is already connected, start tracking that.  
  31.         // Otherwise, the first Ethernet interface to appear will be tracked.  
  32.         try {  
  33.             final String[] ifaces = mNMService.listInterfaces();  
  34.             for (String iface : ifaces) {  
  35.                 synchronized(this) {  
  36.                     if (maybeTrackInterface(iface)) {  
  37.                         // We have our interface. Track it.  
  38.                         // Note: if the interface already has link (e.g., if we  
  39.                         // crashed and got restarted while it was running),  
  40.                         // we need to fake a link up notification so we start  
  41.                         // configuring it. Since we're already holding the lock,  
  42.                         // any real link up/down notification will only arrive  
  43.                         // after we've done this.  
  44.                         if (mNMService.getInterfaceConfig(iface).hasFlag("running")) {  
  45.                             updateInterfaceState(iface, true);  
  46.                         }  
  47.                         break;  
  48.                     }  
  49.                 }  
  50.             }  
  51.         } catch (RemoteException e) {  
  52.             Log.e(TAG, "Could not get list of interfaces " + e);  
  53.         }  
  54.     }  
start()方法接受一个Handler对象作为参数,该参数是在EthernetServiceImpl::start()中传入的,它新建了一个HandlerThread对象,并传入作为参数,从这可知网络管理的操作是运行在EthernetServiceImpl线程中的。
代码中创建了一个LocalNetworkFactory对象。LocalNetworkFactory继承自NetworkFactory:
[java] view plain copy
  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. public class 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.     public void 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.     protected void startNetwork() { }  
  36.     protected void stopNetwork() { }  
  37. ...  
  38. }  
NetworkFactory继承自Handler,我们可以把它动作一个工厂,对网络的请求和终止操作都通过该对象进行处理。从注释可知NetworkFactory与NetworkAgent对象有密切关系,它通过register()方法向CS进行注册。start/stopNetwork()是提供的回调函数 ,我们可以通过这两个函数来请求或终止网络:
[java] view plain copy
  1. public void 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()方法:
[java] view plain copy
  1. @Override  
  2. public void 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内部消息事件的处理。我们直接看处理过程:
[java] view plain copy
  1. case EVENT_REGISTER_NETWORK_FACTORY: {  
  2.                     handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);  
  3.                     break;  
  4.                 }  
[java] view plain copy
  1. private void 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连接的创建:
[java] view plain copy
  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.     public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {  
  13.         if (DBG) log("connect srcHandler to the dstMessenger  E");  
  14.   
  15.         // We are connected  
  16.         connected(srcContext, srcHandler, dstMessenger);  
  17.   
  18.         // Tell source we are half connected  
  19.         replyHalfConnected(STATUS_SUCCESSFUL);  
  20.   
  21.         if (DBG) log("connect srcHandler to the dstMessenger X");  
  22.     }  
[java] view plain copy
  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. public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {  
  12.     if (DBG) log("connected srcHandler to the dstMessenger  E");  
  13.   
  14.     // Initialize source fields  
  15.     mSrcContext = srcContext;  
  16.     mSrcHandler = srcHandler;  
  17.     mSrcMessenger = new Messenger(mSrcHandler);  
  18.   
  19.     // Initialize destination fields  
  20.     mDstMessenger = dstMessenger;  
  21.   
  22.     if (DBG) log("connected srcHandler to the dstMessenger X");  
  23. }  
要明确的是,srcHandler指向CS中的NetworkStateTrackerHandler对象,它主要负责接收网络模块发送的消息,并进行网络更新;mSrcMessenger是代表该Handler对象的一个引用;mDstMessenger则代表EthernetNetworkFactory中的LocalNetworkFactory对象,该对象也是一个Handler。然后向mSrcHandler回复CMD_CHANNEL_HALF_CONNECTED消息:
[java] view plain copy
  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.    private void 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.        /* 
  14.         * Link to death only when bindService isn't used. 
  15.         */  
  16.        if (mConnection == null) {  
  17.            mDeathMonitor = new DeathMonitor();  
  18.            try {  
  19.                mDstMessenger.getBinder().linkToDeath(mDeathMonitor, 0);//为了防止AsyncChannel用于不同进程通信时,若Server端所在的进程已经死掉,来通知  
  20.                                                                     //Client端进程进行一些后期处理  
  21.            } catch (RemoteException e) {  
  22.                mDeathMonitor = null;  
  23.                // Override status to indicate failure  
  24.                msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;  
  25.            }  
  26.        }  
  27.   
  28.        mSrcHandler.sendMessage(msg);  
  29.    }  
CS中是这样处理的:
[java] view plain copy
  1. case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {  
  2.                     handleAsyncChannelHalfConnect(msg);  
  3.                     break;  
  4.                 }  
[java] view plain copy
  1. private void 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.         } else if (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.                     final boolean 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对象,实际的处理是:
[java] view plain copy
  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,它处理该消息:
[java] view plain copy
  1. @Override  
  2. public void 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. }  
[java] view plain copy
  1. private void 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.   
  13.         evalRequest(n);  
  14.     }  
[java] view plain copy
  1. private void 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.         } else if (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():
[java] view plain copy
  1. // override to do fancier stuff  
  2. protected void needNetworkFor(NetworkRequest networkRequest, int score) {  
  3.     if (++mRefCount == 1) startNetwork();  
  4. }  
  5.   
  6. protected void releaseNetworkFor(NetworkRequest networkRequest) {  
  7.     if (--mRefCount == 0) stopNetwork();  
  8. }  
即调用LocalNetworkFactory中的start/stopNetwork()来管理网络的开启和关闭:
[java] view plain copy
  1. private class LocalNetworkFactory extends NetworkFactory {  
  2.     LocalNetworkFactory(String name, Context context, Looper looper) {  
  3.         super(looper, context, name, new NetworkCapabilities());  
  4.     }  
  5.   
  6.     protected void startNetwork() {  
  7.         onRequestNetwork();  
  8.     }  
  9.     protected void stopNetwork() {  
  10.     }  
  11. }  
onRequestNetwork()处理Ethernet的连接操作,包括对静态IP和DHCP的处理。到这里,一个NetworkFactory对象的注册过程就结束了。
我们看onRequestNetwork()方法来触发一个网络的连接:
[java] view plain copy
  1. /* Called by the NetworkFactory on the handler thread. */  
  2. public void onRequestNetwork() {  
  3.     // TODO: Handle DHCP renew.  
  4.     Thread dhcpThread = new Thread(new Runnable() {  
  5.         public void run() {  
  6.             if (DBG) Log.i(TAG, "dhcpThread(" + mIface + "): mNetworkInfo=" + mNetworkInfo);  
  7.             LinkProperties linkProperties;  
  8.   
  9.             IpConfiguration config = mEthernetManager.getConfiguration();  
  10.   
  11.             if (config.getIpAssignment() == IpAssignment.STATIC) {  
  12.                 if (!setStaticIpAddress(config.getStaticIpConfiguration())) {  
  13.                     // We've already logged an error.  
  14.                     return;  
  15.                 }  
  16.                 linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);  
  17.             } else {  
  18.                 mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);  
  19.   
  20.                 DhcpResults dhcpResults = new DhcpResults();  
  21.                 // TODO: Handle DHCP renewals better.  
  22.                 // In general runDhcp handles DHCP renewals for us, because  
  23.                 // the dhcp client stays running, but if the renewal fails,  
  24.                 // we will lose our IP address and connectivity without  
  25.                 // noticing.  
  26.                 if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {  
  27.                     Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());  
  28.                     // set our score lower than any network could go  
  29.                     // so we get dropped.  
  30.                     mFactory.setScoreFilter(-1);  
  31.                     // If DHCP timed out (as opposed to failing), the DHCP client will still be  
  32.                     // running, because in M we changed its timeout to infinite. Stop it now.  
  33.                     NetworkUtils.stopDhcp(mIface);  
  34.                     return;  
  35.                 }  
  36.                 linkProperties = dhcpResults.toLinkProperties(mIface);  
  37.             }  
  38.            ...  
  39.         }  
  40.     });  
  41.     dhcpThread.start();  
  42. }  
CS中处理网络更新的Handler是NetworkStateTrackerHandler。当网络连接后,通知CS更新网络的操作则是通过NetworkAgent对象进行的。从它的定义可知,它也是一个Handler:
[java] view plain copy
  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.   
  10.     // Create our NetworkAgent.  
  11.     mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,  
  12.             NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,  
  13.             NETWORK_SCORE) {  
  14.         public void unwanted() {  
  15.             synchronized(EthernetNetworkFactory.this) {  
  16.                 if (this == mNetworkAgent) {  
  17.                     NetworkUtils.stopDhcp(mIface);  
  18.   
  19.                     mLinkProperties.clear();  
  20.                     mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null,  
  21.                             mHwAddr);  
  22.                     updateAgent();  
  23.                     mNetworkAgent = null;  
  24.                     try {  
  25.                         mNMService.clearInterfaceAddresses(mIface);  
  26.                     } catch (Exception e) {  
  27.                         Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);  
  28.                     }  
  29.                 } else {  
  30.                     Log.d(TAG, "Ignoring unwanted as we have a more modern " +  
  31.                             "instance");  
  32.                 }  
  33.             }  
  34.         };  
  35.     };  
  36. }  
[java] view plain copy
  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.     abstract protected void unwanted();  
重写的unwanted()方法则在CS指出不再需要当前网络连接时调用。除了清除掉网络配置信息,还会把mNetworkAgent置为null。从代码中可以看出,mNetworkAgent是否为null标志了当前是否该类型的网络连接正在使用,如果有则不会处理新的网络请求。
既然网络状态的变化是由NetworkAgent处理的,那我们就接着看NetworkAgent是怎么跟CS通信的:
[java] view plain copy
  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.   
  6.     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,  
  7.             NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {  
  8.         super(looper);  
  9.         LOG_TAG = logTag;  
  10.         mContext = context;  
  11.         if (ni == null || nc == null || lp == null) {  
  12.             throw new IllegalArgumentException();  
  13.         }  
  14.   
  15.         if (VDBG) log("Registering NetworkAgent");  
  16.         ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(  
  17.                 Context.CONNECTIVITY_SERVICE);  
  18.         netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),  
  19.                 new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);  
  20.     }  
在创建NetworkAgent对象时,接受一个特定的Looper对象,并向CS注册该NetworkAgent对象,这与LocalNetworkFactory的处理类似。看CS中具体的注册处理:
[java] view plain copy
  1. public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,  
  2.            LinkProperties linkProperties, NetworkCapabilities networkCapabilities,  
  3.            int currentScore, NetworkMisc networkMisc) {  
  4.        enforceConnectivityInternalPermission();  
  5.   
  6.        // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network  
  7.        // satisfies mDefaultRequest.  
  8.        final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),  
  9.                new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(  
  10.                linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,  
  11.                mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);  
  12.        synchronized (this) {  
  13.            nai.networkMonitor.systemReady = mSystemReady;  
  14.        }  
  15.        addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network);  
  16.        if (DBG) log("registerNetworkAgent " + nai);  
  17.        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));  
  18.        return nai.network.netId;  
  19.    }  
这里的Messager对象是NetworkAgent对象自身的一个引用,创建对应的NetworkAgentInfo对象,其内部创建了一个AsyncChannel对象;messenger参数前面介绍过,mTrackderHandler是NetworkStateTrackerHandler的一个实例。向InternalHandler发送EVENT_REGISTER_NETWORK_AGENT消息,处理注册操作。看CS中的处理:
[java] view plain copy
  1. case EVENT_REGISTER_NETWORK_AGENT: {  
  2.                     handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);  
  3.                     break;  
  4.                 }  
[java] view plain copy
  1. private void 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()处理,只不过走的处理分支不同,有前面的介绍可知:
[java] view plain copy
  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对象发送该消息:
[java] view plain copy
  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:
[java] view plain copy
  1. public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {  
  2.         if (DBG) log("connected srcHandler to the dstMessenger  E");  
  3.   
  4.         // Initialize source fields  
  5.         mSrcContext = srcContext;  
  6.         mSrcHandler = srcHandler;  
  7.         mSrcMessenger = new Messenger(mSrcHandler);  
  8.   
  9.         // Initialize destination fields  
  10.         mDstMessenger = dstMessenger;  
  11.   
  12.         if (DBG) log("connected srcHandler to the dstMessenger X");  
  13.     }  
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()完成此项工作:
[java] view plain copy
  1. public void 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.         mNetworkAgent.sendNetworkInfo(mNetworkInfo);  
  12.         mNetworkAgent.sendLinkProperties(mLinkProperties);  
  13.         // never set the network score below 0.  
  14.         mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0);  
  15.     }  
  16. }  
这里以NetworkInfo的更新为例:
[java] view plain copy
  1. /** 
  2.  * Called by the bearer code when it has new NetworkInfo data. 
  3.  */  
  4. public void sendNetworkInfo(NetworkInfo networkInfo) {  
  5.     queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));  
  6. }  
[java] view plain copy
  1. private void queueOrSendMessage(int what, Object obj) {  
  2.     synchronized (mPreConnectedQueue) {  
  3.         if (mAsyncChannel != null) {  
  4.             mAsyncChannel.sendMessage(what, obj);//mDstMessenger指向CS中的NetworkStateTrackerHandler,mSrcMessenger指向当前NetworkAgent.  
  5.         } else {  
  6.             Message msg = Message.obtain();  
  7.             msg.what = what;  
  8.             msg.obj = obj;  
  9.             mPreConnectedQueue.add(msg);  
  10.         }  
  11.     }  
  12. }  
 通过已经建立的AsyncChannel连接向ConnectifyService发送消息,并附带需要更新的NetworkInfo对象,这样CS中NetworkStateTrackerHandler就可以收到消息,并进行网络状态更新了。
0 0
原创粉丝点击