case NetworkStateTracker.EVENT_STATE_CHANGED:
if (info.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
handleConnectionFailure(info);
} else if (state == NetworkInfo.State.DISCONNECTED) {
handleDisconnect(info);
} else if (state == NetworkInfo.State.SUSPENDED) {
handleDisconnect(info);
} else if (state == NetworkInfo.State.CONNECTED) {
handleConnect(info);
}
break;
DISCONNECTED和SUSPENDED處理方法基本相同只不过在处理sunpended时发送了一个广播。我们先来了解下handleDisconnect()方法,源码中对着个函数是这样介绍的:我将该方法进行拆块分析,贴源码:
int prevNetType = info.getType();
mNetTrackers[prevNetType].setTeardownRequested(false);
/*
* If the disconnected network is not the active one, then don't report
* this as a loss of connectivity. What probably happened is that we're
* getting the disconnect for a network that we explicitly disabled
* in accordance with network preference policies.
*/
if (!mNetConfigs[prevNetType].isDefault()) {
List pids = mNetRequestersPids[prevNetType];
for (int i = 0; i<pids.size(); i++) {
Integer pid = (Integer)pids.get(i);
// will remove them because the net's no longer connected
// need to do this now as only now do we know the pids and
// can properly null things that are no longer referenced.
reassessPidDns(pid.intValue(), false);
}
}
首先获得网络类型,这里先了解下mNetRequestersPids ,它是在函数public int startUsingNetworkFeature(int networkType, String feature,IBinder binder)里面添加进去的,至于这个函数对应ConnecTivityManager里面的函数,在做网络开发时应该会用到,下面再研究这个函数吧,现在先看遍历这些pids调用了reassessPidDns(pid.intValue(), false); 函数都干什么了:
private void reassessPidDns(int myPid, boolean doBump)
{
if (VDBG) log("reassessPidDns for pid " + myPid);
for(int i : mPriorityList) {
if (mNetConfigs.isDefault()) {
continue;
}
NetworkStateTracker nt = mNetTrackers;
if (nt.getNetworkInfo().isConnected() &&
!nt.isTeardownRequested()) {
LinkProperties p = nt.getLinkProperties();
if (p == null) continue;
List pids = mNetRequestersPids;
for (int j=0; j<pids.size(); j++) {
Integer pid = (Integer)pids.get(j);
if (pid.intValue() == myPid) {
Collection<InetAddress> dnses = p.getDnses();
writePidDns(dnses, myPid);
if (doBump) {
bumpDns();
}
return;
}
}
}
}
// nothing found - delete
for (int i = 1; ; i++) {
String prop = "net.dns" + i + "." + myPid;
if (SystemProperties.get(prop).length() == 0) {
if (doBump) {
bumpDns();
}
return;
}
SystemProperties.set(prop, "");
}
}
对该函数的说明为 Adjust the per-process dns entries (net.dns<x>.<pid>) based on the highest priority active net which this process requested. If there aren't any, clear it out。
第一个for以优先权遍历所有网络类型找到符合条件(该网络链接存在,有可能传输数据,且没有被tear down)的网络,再对该网络遍历所有的pids(process id 是system server所有)找到目标参数mypid执行函数writePidDns(dnses, myPid);这个函数是向android系统属性里的开机导入的cache属性写入该网络的ip地址及dns等(前提是该网络没有被写进这个属性)。写入之后changed属性就变为true,这样在每次开机init之后,会执行一个loop循环然后若有改变则会更新。这里doBump为false不执行,因此看下面的那个for循环,这个循环里bumpDns也不执行,而只是将有该pid的所有ip链接清空(第一个for循环return了,就不会执行它了)。bumpDns函数是用以提醒重新从系统属性里面读DNS服务器名单。
下面继续handleDisconnect函数讲解,接下来给参数doReset赋值决定是否改变网络接口名称,(若网络中有重名接口则doReset赋值为false)随后调用了handleConnectivityChange方法(prevNetType, doReset),并发送了一个广播该广播是发送给NetWorkStateService的通知网络接口名称改变了。
至于handleConnecthandleConnect(NetworkInfo info)函数首先判断传进的网络是否为默认网络,若是,且mActiveDefaultNetwork已经设置,且目标type网络不是mActiveDefaultNetwork网络则进入
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
if ((type != mNetworkPreference &&
mNetConfigs[mActiveDefaultNetwork].priority >
mNetConfigs[type].priority) ||
mNetworkPreference == mActiveDefaultNetwork) {
// don't accept this one
if (VDBG) {
log("Not broadcasting CONNECT_ACTION " +
"to torn down network " + info.getTypeName());
}
teardown(thisNet);
return;
// sunxz begin 2012-2-4 for pppoe
} else if(type != ConnectivityManager.TYPE_PPPOE){
// sunxz end 2012-2-4 for pppoe
// tear down the other
NetworkStateTracker otherNet =
mNetTrackers[mActiveDefaultNetwork];
if (DBG) {
log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
" teardown");
}
if (!teardown(otherNet)) {
loge("Network declined teardown request");
teardown(thisNet);
return;
}
}}
在该段函数里(第一个if里)第一个判断是说如果目标type网络不是preference网络且正在运行的网络优先级大于type网络则,或者正在运行的网络是preference网络则关闭(tear down)type网络。else if判断是说若type网络类型若不是pppoe就tear down otherNet或者typeNet,注意进入这两个都会执行return若没有被return则会继续往下执行,看源码:
mActiveDefaultNetwork = type;
// this will cause us to come up initially as unconnected and switching
// to connected after our normal pause unless somebody reports us as reall
// disconnected
mDefaultInetConditionPublished = 0;
mDefaultConnectionSequence++;
mInetConditionChangeInFlight = false;
// Don't do this - if we never sign in stay, grey
//reportNetworkCondition(mActiveDefaultNetwork, 100);
}
thisNet.setTeardownRequested(false);
updateNetworkSettings(thisNet);
handleConnectivityChange(type, false);
sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
}
首先将正在运行的网络的类型改为type,然后再更新一下变量。updateNetworkSettings(thisNet)函数是从系统属性里面读出该网络的属性信息然后把它写到"/sys/kernel/ipv4/tcp_"里面。至此handleConnect函数已经分析完毕了。
下面看函数handleConnectionFailure(NetworkInfo info) Called when an attempt to fail over to another network has failed. @param info the {@link NetworkInfo} for the failed network