Android 网络 --framework层面 -two
在Android 网络 --framework层面-1 中大致描述了android 网络 fwk涉及到一些重要类,本章针对这些较为详细的介绍学习下
NetworkAgent
NetworkAgent 是CS(ConnectivityService)和链路网络管理者(如WifiStateMachine、DataConnection)之间的信使,从CS的角度看NetworkAgent代表了一个网络实体
WIFI在L2连接成功(L2connected 关联4次握手成功 )后构建对象。通过NetworkAgent,WifiStateMachine可以向CS:
- 更新网络状态 NetworkInfo(断一些开、连接中、已连接等)
- 更新链路配置 LinkProperties(本机网口、IP、DNS、路由信息等)
- 更新网络能力 NetworkCapabilities(信号强度、是否收费等)
CS可以向WifiStateMachine:
- 更新网络有效性(即NetworkMonitor的网络检测结果)
- 禁止自动连接
- 由于网络不可上网等原因主动断开网络
data 是在DataConnection进入DcActiveState 状态(拨号成功)构造对象, 此时已经获取到ip dns网络信息,区别于WIFI的L2connected 状态
DataConnection 和 CS交互的信息有很多相似点,这里不在一一罗列了
NetworkAgent 注册的代码片段
在NetworkAgent的构造函数会调用CS的registerNetworkAgent ,Messenger是CS和链路网络管理者"业务往来"的方式
cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp),
new NetworkCapabilities(nc), score, misc);
NetworkAgent在CS中与之对应的是NetworkAgentInfo
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(reserveNetId()), new NetworkInfo(networkInfo), lp,
new NetworkCapabilities(networkCapabilities), currentScore,
mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
- NetworkAgentInfo 是对NetworkAgent 在CS的包装
- Messenger :CS通过这个messenger调用NetworkAgent(client端)的方法
- mTrackHandler :NetworkAgent通过TrackHandler调用的cs的方法,本质也是包装为messenger
- reserveNetId() 生成网络networkid,这个网络id在数据包打mark的时候会用到
registerNetworkAgent最终会调用到CS中的handleRegisterNetworkAgent
private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
if (VDBG) log("Got NetworkAgent Messenger");
mNetworkAgentInfos.put(na.messenger, na);
synchronized (mNetworkForNetId) {
mNetworkForNetId.put(na.network.netId, na);
}
na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
NetworkInfo networkInfo = na.networkInfo;
na.networkInfo = null;
updateNetworkInfo(na, networkInfo);
}
所有的NetworkAgentInfo会保存在mNetworkForNetId中!!
private final SparseArray<NetworkAgentInfo> mNetworkForNetId =
new SparseArray<NetworkAgentInfo>();
最终会调用到
updateNetworkInfo(na, networkInfo);
对于这个方法 处理registerNetworkAgent情境下:
- DcNetworkAgent (数据网络) 在 networkinfo的state在进入DcActiveState状态后设置为NetworkInfo.State.CONNECTED
- WifiNetworkAgent (WIFI网络)在进入mConnectedState-----ip地址配置成功后 sendConnectedState()进入mConnectedState状态
如果networkAgent.created=false 该网络从未创建过,且NetworkInfo.State.CONNECTED
在netd里面创建一个PhysicalNetwork,一个netid 对一个PhysicalNetwork(netd PhysicalNetwork .cpp)
mNetd.createPhysicalNetwork(networkAgent.network.netId,
getNetworkPermission(networkAgent.networkCapabilities));
如果networkAgent.everConnected = false ,从来没有连接过且 NetworkInfo.State.CONNECTED 更新链路信息,包括 updateInterfaces、updateMtu、updateTcpBufferSizes、updateRoutes、updateDnses
- updateInterfaces通过调用netd的addInterfaceToNetwork,此例子是通过PhysicalNetwork的
- addInterface 方法,给IncomingPacket的打mark 和 设置策略路由
- 关于和netd交互的两点,会在netd章节中学习下
最后rematchNetworkAndRequests网络,因为只有一个网络传入REAP
REAP 意思就是如果没有一个network request匹配上这个NetworkAgentInfo,就会tear down 该network,这个很好理解,既然没有网络请求需要这个NetworkAgentInfo,那就没有存在的必要了
rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
rematchNetworkAndRequests–非常核心的方法!!
理解这个方法,CS基本掌握一大半了!!
rematchNetworkAndRequests(NetworkAgentInfo newNetwork,
ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now)
- 这个方法的做的事情总结一句话 Handles a network appearing or improving its score.
- 新的NetworkAgentInfo出来,要重新评估所有的NetworkRequests,如果这个网络是最好的网络,会将这些NetworkRequests reassigns到这个新网络, 比如数据网络连接的情况下,wifi连接成功且网络判通成功,这时候一些网络请求的NetworkRequests 要reassigns 到wifi的NetworkAgentInfo
- Lingers任何一个不再需要的validated Networks,理解 “不再需要”,wifi连接的情况下,data网络正常是会linger的,但是如果此时有一个或多个NetworkRequest的指定的transportType为NetworkCapabilities.TRANSPORT_CELLULAR 此时不会linger这个数据网络,另外这个网络是VPN.也不会被linger
- 如果一个不需要的网络,就是被linger的网络,会执行Tears down newNetwork ,导致networkagent调用unwanted()方法 网络interface 都会被关闭(可以通过ifconfig 中消失掉来验证)
- reapUnvalidatedNetworks 最后一个网络会传REAP,导致网络被tear down
"理解最好的网络!!!----------------------该方法核心!!! "
把newNetwork 和当前所有的newtworkRequest (保存在mNetworkRequests)做satisfies,如果“满足”了,
且下面三种条件之一成立的:|| 或的关系
- currentNetwork == null 当前的网络为null,比如在无任何网络的情况下,打开数据网络,"当前的网络为null ",当然会创建新的默认网络
- isBestMobileMultiNetwork() — 此方法未研究–记得7.0没有,应该和双卡有关系,貌似选择默认数据网络卡会走这个
- currentNetwork.getCurrentScore() < score 当前网络分数小于newNetwork的分数,会切换default网络
把request从currentNetwork remove掉,并添加到newNetwork中,如果currentNetwork没有一个网络request,自然就需要 linger掉了!!
把request从currentNetwork remove掉
//把request从currentNetwork remove掉
currentNetwork.removeRequest(nri.request.requestId);
// 把nri.request 添加到mLingerTimerForRequest
currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs);
// 把request添加到新的newNetwork
setNetworkForRequest(nri.request.requestId, newNetwork);
如果满足再满足isDefaultRequest条件下:
会导致新的default网络的出现,看下makeDeault到底干啥,设置default的路由的(netd章节会介绍学习下)
// Log 0 -> X and Y -> X default network transitions, where X is the new default.
private void makeDefault(NetworkAgentInfo newNetwork) {
if (DBG) log("Switching to new default network: " + newNetwork);
try {
mNetd.setDefaultNetId(newNetwork.network.netId);
} catch (Exception e) {
loge("Exception setting default network :" + e);
}
// 通过prop可以读取dns的直
setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
总结:
本章介绍学习了NetworkAgent和CS中重要的rematchNetworkAndRequests方法,理解这个方法是理解CS的关键点,甚者可以说是理解android fwk 网络的关键点 !!