"A NetworkFactory is an entity that creates NetworkAgent objects."这说明NetworkFactory的主要作用还是用来创建NetworkAgent的,那么NetworkAgent是什么对象,而NetworkFactory与NetworkAgent又是什么关系呢?
我们接下来介绍NetworkAgent。
下面我们跟踪一下数据连接的创建过程来看一下NetworkAgent的使用。
@DataConnection.java private class DcActiveState extends State { @Override public void 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); } }我们看到,当数据连接建立成功后,就会更新当前的NetworkInfo( 点击这里了解NetworkInfo),然后创建当前的NetworkAgent,并把NetworkInfo传递给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) { throw new 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); }在NetworkAgent的创建过程中,只做了一件事情,就是将其注册到ConnectivityService中,而这里传递的参数包含当前NetworkAgent的Messenger(用于与ConnectivityService之间建立AsyncChannel通道)、传递进来的NetworkInfo、NetworkCapabilities、以及当前连接的分数score等。
@ConnectivityService.java public void 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)); }我们看到,当NetworkAgent注册时,在ConnectivityService的内部创建了一个新的对象NetworkAgentInfo,该对象中保留了传递进来的一系列参数,包括NetworkAgent的Messenger对象、NetworkInfo、NetworkCapabilities、score以及创建了一个用于通讯的AsyncChannel通道。
@ConnectivityService.java private class InternalHandler extends Handler { public void handleMessage(Message msg) { NetworkInfo info; switch (msg.what) { case EVENT_REGISTER_NETWORK_AGENT: { handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj); break; } } } }继续:
private void 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); }在这里,ConnectivityService做了三个事情:
@ConnectivityService.java private class NetworkStateTrackerHandler extends Handler { public void handleMessage(Message msg) { NetworkInfo info; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { handleAsyncChannelHalfConnect(msg); break; } } } }然后来看详细处理:
private void handleAsyncChannelHalfConnect(Message msg) { AsyncChannel ac = (AsyncChannel) msg.obj; if (mNetworkFactoryInfos.containsKey(msg.replyTo)) { } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) { if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { //向NetworkAgent发起双向连接请求 mNetworkAgentInfos.get(msg.replyTo).asyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); } else { } } }我们看到,当ConnectivityService与NetworkAgent之间单向通道建立完成后, 又发起了双向通道的请求,此时在NetworkAgent端,将会收到CMD_CHANNEL_FULL_CONNECTION的消息:
@NetworkAgent.java public void handleMessage(Message msg) { switch (msg.what) { case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { if (mAsyncChannel != null) { } else { AsyncChannel ac = new AsyncChannel(); ac.connected(null, this, msg.replyTo); //连接建立成功 ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL); synchronized (mPreConnectedQueue) { mAsyncChannel = ac; for (Message m : mPreConnectedQueue) { //如果有缓存消息,则发送出去 ac.sendMessage(m); } mPreConnectedQueue.clear(); } } break; } } }从NetworkAgent的消息处理中我们看到他收到请求之后就发送了建立成功的消息,然后检测消息队列,如果有消息就及时向ConnectivityService传递。
至此,NetworkAgent的初始化完毕。
在网络连接过程中,根据网络情况,各个网络的NetworkFactory可以修改当前的NetworkAgent分值,此操作将会把最新的分值广播到系统内所有的NetworkFactory中,从而引发上面描述的评分过程,而更新NetworkAgent分值有两种方式,分别是:直接更新分值、通过sendNetworkInfo更新。下面我们分别来看这两种过程。
@WifiStateMachine.java private void calculateWifiScore(WifiLinkLayerStats stats) { //初始值56 int score = 56; // Starting score, temporarily hardcoded in between 50 and 60 if (isBadLinkspeed) { //网速过低,扣4分 score -= 4 ; } else if ((isGoodLinkspeed) && (mWifiInfo.txSuccessRate > 5)) { //否则加4分 score += 4; // So as bad rssi alone dont kill us } score -= mWifiInfo.badRssiCount * 2 + mWifiInfo.lowRssiCount ; //是否干扰太大 if (isHighRSSI) { score += 5; } //调整分值,最大为60,最小为0 if (score > NetworkAgent.WIFI_BASE_SCORE) score = NetworkAgent.WIFI_BASE_SCORE; if (score < 0) score = 0; if (score != mWifiInfo.score) { mWifiInfo.score = score; if (mNetworkAgent != null) { //更新当前分值 mNetworkAgent.sendNetworkScore(score); } } }在上面这个方法中,我们看到最终的分数将会通过sendNetworkScore方法更新到NetworkAgent中:
@NetworkAgent.java public void sendNetworkScore(int score) { if (score < 0) { throw new IllegalArgumentException("Score must be >= 0"); } queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score)); }继续:
private void queueOrSendMessage(int what, Object obj) { synchronized (mPreConnectedQueue) { if (mAsyncChannel != null) { mAsyncChannel.sendMessage(what, obj); } else { Message msg = Message.obtain(); msg.what = what; msg.obj = obj; mPreConnectedQueue.add(msg); } } }我们看到,NetworkAgent将会把最新的分值封装到EVENT_NETWORK_SCORE_CHANGED消息中,通过AsyncChannel发送出去,而这里的AsyncChannel通道就是当初NetworkAgent向ConnectivityService注册时由ConnectivityService发起的双向通道,也就是说,该消息将会被ConnectivityService中的mTrackerHandler处理:
@ConnectivityService.java private class NetworkStateTrackerHandler extends Handler { public void handleMessage(Message msg) { NetworkInfo info; switch (msg.what) { case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: { NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo); if (nai == null) { break; } Integer score = (Integer) msg.obj; //更新ConnectivityService中的NetworkAgent分值 if (score != null) updateNetworkScore(nai, score.intValue()); break; } } } }在ConnectivityService收到该消息后,就通过updateNetworkScore方法来更新NetworkAgent分值:
private void updateNetworkScore(NetworkAgentInfo nai, int score) { if (score < 0) { score = 0; } final int oldScore = nai.getCurrentScore(); //将分值更新到NetworkAgentInfo中 nai.setCurrentScore(score); //触发评分机制 if (nai.created) rematchAllNetworksAndRequests(nai, oldScore); //将当前最新分值更新到每个NetworkFactory中 sendUpdatedScoreToFactories(nai); }在这个过程中,ConnectivityService将会把最新的分值更新到NetworkAgentInfo中,最后通过sendUpdatedScoreToFactories方法将此评分送达到每个NetworkFactory中。
private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, boolean nascent) { for (NetworkRequestInfo nri : mNetworkRequests.values()) { //寻找当前NetworkRequest所使用的NetworkAgent if (nri.request.networkCapabilities.satisfiedByNetworkCapabilities( newNetwork.networkCapabilities)) { //如果当前NetworkRequest使用的NetworkAgent分数低于新的NetworkAgent分数,将会用新的NetworkAgent替代 if (currentNetwork == null || currentNetwork.getCurrentScore() < newNetwork.getCurrentScore()) { //找到新的NetworkAgent替代方案 if (currentNetwork != null) { if (DBG) log(" accepting network in place of " + currentNetwork.name()); currentNetwork.networkRequests.remove(nri.request.requestId); currentNetwork.networkLingered.add(nri.request); affectedNetworks.add(currentNetwork); } else { if (DBG) log(" accepting network in place of null"); } mNetworkForRequestId.put(nri.request.requestId, newNetwork); newNetwork.addRequest(nri.request); if (nri.isRequest && nri.request.legacyType != TYPE_NONE) { mLegacyTypeTracker.add(nri.request.legacyType, newNetwork); } keep = true; //将分数更新到各个NetworkFactory中 sendUpdatedScoreToFactories(nri.request, newNetwork.getCurrentScore()); } } } }我们再看一下通知NetworkFactory的方法:
private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) { for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) { //将分值发送到各个NetworkFactory nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0, networkRequest); } }
至此,ConnectivityService就将最新的NetworkAgent分值通过AsyncChannel通道发送给各个NetworkFactory,由NetworkFactory来决定自己的网络是否需要建立连接或者释放连接。
@WifiStateMachine.java private void handleNetworkDisconnect() { //断开时,状态应该设置为DISCONNECTED setNetworkDetailedState(DetailedState.DISCONNECTED); }将WIFI状态更新为DISCONNECTED:
private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) { if (state != mNetworkInfo.getDetailedState()) { //将DISCONNECTED状态更新到WIFI的NetworkAgent中 mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID()); if (mNetworkAgent != null) { //将NetworkAgent更新到ConnectivityService中 mNetworkAgent.sendNetworkInfo(mNetworkInfo); } return true; } return false; }我们看到,最终通过sendNetworkInfo方法将最新的NetworkInfo更新到NetworkAgent中:
@NetworkAgent.java public void sendNetworkInfo(NetworkInfo networkInfo) { queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo)); }与sendNetworkScore类似,NetworkAgent也将把最新的NetworkInfo通过AsyncChannel消息同步到ConnectivityService中:
@ConnectivityService.java private class NetworkStateTrackerHandler extends Handler { public void handleMessage(Message msg) { NetworkInfo info; switch (msg.what) { case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: { NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo); info = (NetworkInfo) msg.obj; updateNetworkInfo(nai, info); break; } } } }ConnectivityService通过updateNetworkInfo来更新NetworkInfo:
private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) { NetworkInfo.State state = newInfo.getState(); NetworkInfo oldInfo = null; synchronized (networkAgent) { oldInfo = networkAgent.networkInfo; networkAgent.networkInfo = newInfo; } if (state == NetworkInfo.State.CONNECTED && !networkAgent.created) { //网络连接上 networkAgent.created = true; updateLinkProperties(networkAgent, null); notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK); networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED); rematchNetworkAndRequests(networkAgent, false); } else if (state == NetworkInfo.State.DISCONNECTED || state == NetworkInfo.State.SUSPENDED) { //网络断开 networkAgent.asyncChannel.disconnect(); } }在这里我们看到,updateNetworkInfo的方法中将会对最新状态进行分类,如果是连接状态,则会触发rematchNetworkAndRequests,这个过程将会和上面直接更新分值的过程一致,而如果是断开状态,则直接把AsyncChannel通道断开即可,此时将会在ConnectivityService中收到CMD_CHANNEL_DISCONNECTED的消息:
private class NetworkStateTrackerHandler extends Handler { public void handleMessage(Message msg) { NetworkInfo info; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { handleAsyncChannelDisconnected(msg); break; } } } }然后进入handleAsyncChannelDisconnected方法:
private void handleAsyncChannelDisconnected(Message msg) { NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo); if (nai != null) { //删掉当前NetworkAgent对象 mNetworkAgentInfos.remove(msg.replyTo); final ArrayList<NetworkAgentInfo> toActivate = new ArrayList<NetworkAgentInfo>(); for (int i = 0; i < nai.networkRequests.size(); i++) { NetworkRequest request = nai.networkRequests.valueAt(i); NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId); if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) { mNetworkForRequestId.remove(request.requestId); //将0分更新到各个NetworkFactory中 sendUpdatedScoreToFactories(request, 0); } } } }在这里,由于当前连接是断开状态,因此其分值必然为0,这样就把他的0分值通知到各个NetworkFactory中,由NetworkFactory判断是否需要开启自己的网络。