前面介绍了开机过程中各个网络提供者的初始化过程,其实就是创建自己的NetworkFactory,并将其注册到ConnectivityService。而在介绍NetworkFactory的时候,我们看到该类的官方注释中有这么一句描述:
从刚才NetworkFactory的注释我们知道,NetworkAgent是被NetworkFactory创建的,这里的创建并不是说在NetworkFactory内部创建NetworkAgent,而是说, 在NetworkFactory这个环境就绪之后,网络提供者才可以创建NetworkAgent。并且在一个NetworkFactory中可以创建不同的NetworkAgent,他们拥有不同的Capabilities等参数。
而他们之间还有一个区别就是,NetworkFactory是在 系统初始化时就被创建,而NetworkAgent是在 真正接入网络时才会创建。
我们用运营商之间的关系来比喻他们的关系。
NetworkFactory相当于不同的运营商,比如中国电信、铁通、移动,他们具备联通互联网的能力,当用户入网时就决定了自己的运营商(即完成NetworkFactory初始化)。但同时在每个运营商内部又创建各个不同的接入点,比如对于中国电信来说,还分为上海电信、河北电信等,只有当用户打开电脑真正上网的时候,才会被分配具体的接入点(即完成NetworkAgent初始化)。
也就是说,同一个NetworkFactory可以在不同的时刻根据需要创建不同的NetworkAgent,比如使用数据上网时,会根据当前的需要(发送MMS还是IMS,或者单纯上网)来创建不同参数的NetworkAgent(不同的APN参数)对象,然后将其注册到ConnectivityService中。
下面我们来看NetworkAgent的创建过程:
然后我们继续来看在ConnectivityService中的注册过程:
然后就把当前创建的NetworkAgentInfo对象放入EVENT_REGISTER_NETWORK_AGENT消息中,发送给Handler处理:
1、将新注册的NetworkAgentInfo保存到mNetworkAgentInfos中;
2、利用刚才创建的AsyncChannel向NetworkAgent发起单向连接请求;
3、更新最新的NetworkAgentInfo状态;
我们主要关注第二个过程,而第三个过程将会在接下来小节中介绍。
根据AsyncChannel的原理( 不懂的点这里),此时ConnectivityService发起的是单向的AsyncChannel连接,发起后将会在mTrackerHandler中收到CMD_CHANNEL_HALF_CONNECTED的消息:
那么网络请求中的分值来自于哪里呢?其实就是来自于NetworkAgent。
但是该过程还有一个重要的作用,就是通过rematchAllNetworksAndRequests方法将当前的NetworkRequest分配给合适的NetworkAgent,最后把当前最合适的NetworkAgent分数同步给所有的NetworkFactory。
比如当WIFI被关闭时,将会把WIFI的状态置为断开状态,然后通知到ConnectivityService:
也就是说,无论是直接更新NetworkAgent中的分数,还是更新NetworkAgent的状态,最终都会触发NetworkFactory中的评分机制。
"A NetworkFactory is an entity that creates NetworkAgent objects."
这说明NetworkFactory的主要作用还是用来创建NetworkAgent的,那么NetworkAgent是什么对象,而NetworkFactory与NetworkAgent又是什么关系呢?
我们接下来介绍NetworkAgent。
一、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.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);
- }
- }
@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的创建过程:
- @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.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中的注册过程:
- @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));
- }
@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通道。
然后就把当前创建的NetworkAgentInfo对象放入EVENT_REGISTER_NETWORK_AGENT消息中,发送给Handler处理:
- @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;
- }
- }
- }
- }
@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);
- }
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做了三个事情:
1、将新注册的NetworkAgentInfo保存到mNetworkAgentInfos中;
2、利用刚才创建的AsyncChannel向NetworkAgent发起单向连接请求;
3、更新最新的NetworkAgentInfo状态;
我们主要关注第二个过程,而第三个过程将会在接下来小节中介绍。
根据AsyncChannel的原理( 不懂的点这里),此时ConnectivityService发起的是单向的AsyncChannel连接,发起后将会在mTrackerHandler中收到CMD_CHANNEL_HALF_CONNECTED的消息:
- @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;
- }
- }
- }
- }
@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 {
- }
- }
- }
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.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的初始化完毕。
三、NetworkAgent更新过程
那么网络请求中的分值来自于哪里呢?其实就是来自于NetworkAgent。
在网络连接过程中,根据网络情况,各个网络的NetworkFactory可以修改当前的NetworkAgent分值,此操作将会把最新的分值广播到系统内所有的NetworkFactory中,从而引发上面描述的评分过程,而更新NetworkAgent分值有两种方式,分别是:直接更新分值、通过sendNetworkInfo更新。下面我们分别来看这两种过程。
3.1、直接更新分值过程
- @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);
- }
- }
- }
@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));
- }
@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);
- }
- }
- }
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.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);
- }
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中。
但是该过程还有一个重要的作用,就是通过rematchAllNetworksAndRequests方法将当前的NetworkRequest分配给合适的NetworkAgent,最后把当前最合适的NetworkAgent分数同步给所有的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());
- }
- }
- }
- }
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);
- }
- }
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来决定自己的网络是否需要建立连接或者释放连接。
3.2、间接更新分值过程
比如当WIFI被关闭时,将会把WIFI的状态置为断开状态,然后通知到ConnectivityService:
- @WifiStateMachine.java
- private void handleNetworkDisconnect() {
- //断开时,状态应该设置为DISCONNECTED
- setNetworkDetailedState(DetailedState.DISCONNECTED);
- }
@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;
- }
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));
- }
@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.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();
- }
- }
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;
- }
- }
- }
- }
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);
- }
- }
- }
- }
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判断是否需要开启自己的网络。
也就是说,无论是直接更新NetworkAgent中的分数,还是更新NetworkAgent的状态,最终都会触发NetworkFactory中的评分机制。