Android4.4 framework网络管理

昨晚梦见老家的那条小狗好几天没有回家,担心是不是被人偷去吃了,每天都有一些奇怪的梦…….

今天总结一下Android4.4 framework网络管理流程,同样,Android5.0这部分改动很大,在此先不介绍Android5.0的情况。

整体框架

fd
图1. 结构框图

每一个网络都会实现一个NetworkStateTracker,例如WIFI对于的是WifiStateTracker,Ethernet对于的EthernetStateTracker。NetworkStateTracker在网络连接状态发生改变时,会发送消息EVENT_STATE_CHANGED给ConnectivityService。

同时,ConnectivityService可以透过NetworkStateTracker获得网络连接状态(getNetworkInfo)和网络连接信息(getLinkProperties)。

此外,NetworkStateTracker还会向NetworkManagerService注册一个BaseNetworkObserver,用于获取内核发上来的uevent事件,包括interfaceAdded(网口添加)、interfaceRemoved(网口移除)、interfaceLinkStateChanged(网线link up/down)、interfaceStatusChanged(网口up/down)等事件。

ConnectivityService会设置系统的路由和dns,NetworkManagerService是netd进程与SystemServer进程通讯的枢纽,NetworkManagerService在设置路由或者dns时,会通过socket发送给netd,netd再将其设置到kernel中去,同样,kernel有网络事件是通过netlink发送到netd,netd经socket通知到NetworkManagerService,NetworkManagerService再分发到每个NetworkStateTracker。

网络状态管理

NetworkStateTracker将自己的状态发送给ConnectivityService,由它来统一管理,原生Android4.4只允许一个default型网络存在,通过修改framework可以做到WIFI Ethernet同时连接,这点后面再介绍;

ConntivityService中的NetworkStateTrackerHandler接收发自NetworkStateTracker发过来的message,判断当前该网络的状态,不同的状态做不同的处理。

if (info.getDetailedState() ==
        NetworkInfo.DetailedState.FAILED) { /* 连接失败 */
    handleConnectionFailure(info);
} else if (state == NetworkInfo.State.DISCONNECTED) { /* 断开连接 */
    handleDisconnect(info);
} else if (state == NetworkInfo.State.CONNECTED) { /* 已连接 */
    handleConnect(info);
}

某一个网络(thisNet)已连接后,先判断此前是否已经有网络(otherNet)连接上了,如果有,则判断preNetType和newNetType谁的优先级高,teardown掉优先级低的网络。

if (isNewNetTypePreferredOverCurrentNetType(newNetType)) {
    teardown(otherNet)
} else {
    teardown(thisNet)
}

如何判断优先级?对比定义在frameworks\base\core\res\res\values\config.xml中的networkAttributes,谁的priority数值大则谁的优先级高。

<string-array translatable="false" name="networkAttributes">
    <item>"wifi,1,1,1,-1,true"</item>
    <item>"bluetooth,7,7,1,60000,true"</item>
    <item>"ethernet,9,9,2,-1,true"</item>
</string-array>

很明显上面三个网络的优先级是ethernet > bluetooth > wifi;
还有一个地方会影响到网络优先级评判的,那就是frameworks\base\packages\SettingsProvider\res\values\defaults.xml中所定义的
<integer name="def_network_preference">9</integer>
这个指定了网络首选项,设置成首选项的网络优先级总是高于其他网络的,这个设置网络首选项为ethernet,radio-type = 9。

被teardown的网络就断开连接了,但是值得注意的是teardown和disconnect是不一样的,teardown的时候会设置mTeardownRequested.set(true),这样的话只是临时断开连接,如果优先级高的网络断开连接后,ConnectivityService还会把它恢复回来,而disconnect是没有设置的,不允许被恢复连接。

当一个网络断开连接后,会先尝试恢复可以恢复网络。

不管是网络已连接(handleConnect)还是网络断开连接(handleDisconnect),都会调用handleConnectivityChange去设置系统的route和dns,最后发送ConnectivityManager.CONNECTIVITY_ACTION给感兴趣的应用程序。

网络配置管理

直接看handleConnectivityChange这个函数,handleConnectivityChange有两个工作,更新dns和更新路由表。

1) 更新dns

dns只有update操作,没有删除操作,所以当一个网络断开连接之后,handleDnsConfigurationChange里面是什么也不做的,当一个网络已连接之后,会先判断这个网络是否default型,什么是default型网络呢?default型网络就是固定的网络类型,如果config.xml中定义的”networkAttributes”和”radioAttributes”相等则是default型网络,可见常见的wifi和ethernet都是default,而vpn不是。

如果mNetConfigs[netType].isDefault()为真,则将这个网络的dns server设置到系统的默认dns。

updateDnsLocked(network, p.getInterfaceName(), dnses, p.getDomains(), true);

这个函数会做两件事,1、mNetd.setDnsServersForInterface,2、mNetd.setDefaultInterfaceForDns,当然也会将dns server设置到系统属性net.dns[n]中去,其实设置这个系统没什么用,一般情况下不会被使用到。

如果不设置到系统的默认dns,则使用下面的函数:

updateDnsLocked(network, p.getInterfaceName(), dnses, p.getDomains(), false);

这样就不会setDefaultInterfaceForDns,setDefaultInterfaceForDns才是设置系统dns的关键。

2) 更新route

更新route之前,先对比一下该网络类型上次的连接信息(curLp)和该次的连接信息(newLp):

LinkProperties curLp = mCurrentLinkProperties[netType];
LinkProperties newLp = mNetTrackers[netType].getLinkProperties();

注意:如果该网络在连接之前是断开的,则curLp = null,因为每次断开连接的时候都会把linkProperties清掉,如果网络连接状态没有改变,只是连接信息发生了改变,则curLp和newLp都可能非空。

比较curLp和newLp之后,添加路由:

for (RouteInfo r :  routeDiff.added) {
    if (isLinkDefault || ! r.isDefaultRoute()) {
        addRoute(newLp, r, TO_DEFAULT_TABLE, exempt);
    } else {
        // add to a secondary route table
        addRoute(newLp, r, TO_SECONDARY_TABLE, UNEXEMPT);
    }
}

删除路由:

 for (RouteInfo r : routeDiff.removed) {
     if (isLinkDefault || ! r.isDefaultRoute()) {
         if (VDBG) log("updateRoutes: default remove route r=" + r);
         removeRoute(curLp, r, TO_DEFAULT_TABLE);
     }
     if (isLinkDefault == false) {
         // remove from a secondary route table
         removeRoute(curLp, r, TO_SECONDARY_TABLE);
     }
 }

isLinkDefault = mNetConfigs[netType].isDefault(),可见default网络的全部路由,和非default网络的非默认路由都放在TO_DEFAULT_TABLE中。

总结

最后来画一个图吧……
这里写图片描述
图2. 流程图

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值