Android 9.0 网络评分之--NetworkAgent
Posted Mrsongs的心情杂货铺
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 9.0 网络评分之--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 的构造函数中会调用ConnectivityService的registerNetworkAgent方法注册。
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();
if (VDBG) log("Registering NetworkAgent");
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
但是NetworkAgent 方法是在哪里实例化的呢 ? 是在 EthrernetNetworkFactory里面,具体流程我们接着分析。在framework下全局代码搜索的时候可以看到NetworkAgent 是在EthernetNetworkFactory 里面实例化的。
代码路径:frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
void onIpLayerStarted(LinkProperties linkProperties)
if (mNetworkAgent != null)
Log.e(TAG, “Already have a NetworkAgent - aborting new request”);
// wtf: why stop current agent??
//stop();
return;
mLinkProperties = linkProperties;
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddress);
mNetworkInfo.setIsAvailable(true);
// set specifier caps for automotive multiple ETH devices such as meter tbox and generic eth.
mCapabilities.setNetworkSpecifier(new StringNetworkSpecifier(mLinkProperties.getInterfaceName()));
// Create our NetworkAgent.
mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext,
NETWORK_TYPE, mNetworkInfo, mCapabilities, mLinkProperties,
NETWORK_SCORE)
public void unwanted()
if (this == mNetworkAgent)
// wtf: why stop current agent??
//stop();
else if (mNetworkAgent != null)
Log.d(TAG, "Ignoring unwanted as we have a more modern " +
"instance");
// Otherwise, we've already called stop.
;
onIpLayerStarted 是IpClient 中的一个callback 回调中调用
private final IpClient.Callback mIpClientCallback = new IpClient.Callback()
@Override
public void onProvisioningSuccess(LinkProperties newLp)
mHandler.post(() -> onIpLayerStarted(newLp));
@Override
public void onProvisioningFailure(LinkProperties newLp)
mHandler.post(() -> onIpLayerStopped(newLp));
@Override
public void onLinkPropertiesChange(LinkProperties newLp)
mHandler.post(() -> updateLinkProperties(newLp));
;
二、什么是IpClient
Google官网链接:https://source.android.google.cn/devices/architecture/modular-system/networking
IP 服务。 IpClient(以前称为 IpManager)组件负责处理 IP 层配置和维护。在 Android 9 中,它被蓝牙等组件用于进程间处理,被 WLAN 等组件用于进程内处理。DhcpClient 组件从 DHCP 服务器获取 IP 地址,以便将它们分配给接口。
IpClient:
EtherNetworkFactory 中有一个内部类NetworkInterfaceState,这个内部类主要记录链路状态和属性。
其中就有ipclient。ipclient 涉及ip的DHCP请求与分配,他的本质是一个状态机。
private static class NetworkInterfaceState
final String name;
private final String mHwAddress;
private final NetworkCapabilities mCapabilities;
private final Handler mHandler;
private final Context mContext;
private final NetworkInfo mNetworkInfo;
private static String sTcpBufferSizes = null; // Lazy initialized.
private boolean mLinkUp;
private LinkProperties mLinkProperties = new LinkProperties();
private IpClient mIpClient;
private NetworkAgent mNetworkAgent;
private IpConfiguration mIpConfig;
但IpClient 底层是怎么一步步调用上来的呢,这个要去跟一下代码一步步看了。
三、IpClient的初始化过程
3.1、EthernetTracker 中监听到有新的网络接口被添加了,会调用 maybeTrackInterface
EthernetTracker 是一个监听网络接口状态变化的类,他通过观察者模式和NetworkManagementService连系起来,而NetworkManagementService最终又是与NetD关联的,NetD是与kernel关联的,有兴趣的可以往下一步步跟一下代码,这篇文章不贴出来了。
代码路径:frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java
@Override
public void interfaceAdded(String iface)
if (DBG)
Log.i(TAG, "szh,interfaceAdded, iface: " + iface);
mHandler.post(() -> maybeTrackInterface(iface));
3.2、maybeTrackInterface 方法会调用updateIpConfiguration更新网络接口的IP配置信息,同时添加网口。
private void maybeTrackInterface(String iface)
if (DBG) Log.i(TAG, "maybeTrackInterface " + iface);
// If we don't already track this interface, and if this interface matches
// our regex, start tracking it.
if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface))
return;
if (mIpConfigForDefaultInterface != null)
updateIpConfiguration(iface, mIpConfigForDefaultInterface);
mIpConfigForDefaultInterface = null;
addInterface(iface);
3.3、调用NetworkFactory的updateIpConfiguration方法去更新updateIpConfiguration
这里面EthernetTracker 的updateIpConfiguration 将IP配置信息放到 mIpConfigurations 中最终调用的是 EthernetNetworkFactory 的updateIpConfiguration。
void updateIpConfiguration(String iface, IpConfiguration ipConfiguration)
if (DBG)
Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration);
mConfigStore.write(iface, ipConfiguration);
mIpConfigurations.put(iface, ipConfiguration);
mHandler.post(() -> mFactory.updateIpConfiguration(iface, ipConfiguration));
EthernetNetworkFactory 中调用updateIPConfiguration,然后设置ip配置信息
void updateIpConfiguration(String iface, IpConfiguration ipConfiguration)
NetworkInterfaceState network = mTrackingInterfaces.get(iface);
if (network != null)
network.setIpConfig(ipConfiguration);
继续:
void setIpConfig(IpConfiguration ipConfig)
this.mIpConfig = ipConfig;
stop();
start();
3.4、然后看start方法里面初始化里IPClient这个对象。
private void start()
if (mIpClient != null)
if (DBG) Log.d(TAG, "IpClient already started");
return;
if (DBG)
Log.d(TAG, String.format("starting IpClient(%s): mNetworkInfo=%s", name,
mNetworkInfo));
mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddress);
mIpClient = new IpClient(mContext, name, mIpClientCallback);
if (sTcpBufferSizes == null)
sTcpBufferSizes = mContext.getResources().getString(
com.android.internal.R.string.config_ethernet_tcp_buffers);
provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes);
四、NetworkAgent与ConnectivityService的连接过程
ConnectivityManager.registerNetworkAgent–>ConnectivityService.registerNetworkAgent
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();
if (VDBG) log("Registering NetworkAgent");
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
在ConnectivityService registerNetworkAgent中有新的NetworkAgent 注册之后会更新LinkProperties
public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkMisc networkMisc)
enforceConnectivityInternalPermission();
LinkProperties lp = new LinkProperties(linkProperties);
lp.ensureDirectlyConnectedRoutes();
// TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
// satisfies mDefaultRequest.
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
// Make sure the network capabilities reflect what the agent info says.
nai.networkCapabilities = mixInCapabilities(nai, nc);
synchronized (this)
nai.networkMonitor.systemReady = mSystemReady;
final String extraInfo = networkInfo.getExtraInfo();
final String name = TextUtils.isEmpty(extraInfo)
? nai.networkCapabilities.getSSID() : extraInfo;
addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network, name);
if (DBG) log("registerNetworkAgent " + nai);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
return nai.network.netId;
发送EVENT_REGISTER_NETWORK_AGENT 去更新updateNetworkInfo 这些网络状态,并且连接NetworkAgent的 AsyncChannel
private void handleRegisterNetworkAgent(NetworkAgentInfo nai)
if (VDBG) log(“Got NetworkAgent Messenger”);
mNetworkAgentInfos.put(nai.messenger, nai);
synchronized (mNetworkForNetId)
mNetworkForNetId.put(nai.network.netId, nai);
nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
NetworkInfo networkInfo = nai.networkInfo;
nai.networkInfo = null;
updateNetworkInfo(nai, networkInfo);
updateUids(nai, null, nai.networkCapabilities);
这里连接上了,然后建立双向连接
else if (mNetworkAgentInfos.containsKey(msg.replyTo))
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL)
if (VDBG) log(“NetworkAgent connected”);
// A network agent has requested a connection. Establish the connection.
mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
参考博客链接 :https://blog.csdn.net/u010961631/article/details/48971651
以上是关于Android 9.0 网络评分之--NetworkAgent的主要内容,如果未能解决你的问题,请参考以下文章
Android 9.0 网络评分之---NetworkFactory
Android 9.0 网络评分之--NetworkAgent
Android 9.0 网络评分之--NetworkAgent
Android 9.0 网络评分之--NetworkAgent