android N之前 Ethernet旧的ip获取
Android N之前,即android 5.0和android 6.0的IP获取机制都是通过/system/bin下面的dhcpcd的bin档去拿的ip
//EthernetNetworkFactory.java (frameworks\opt\net\ethernet\java\com\android\server\ethernet)
public void onRequestNetwork() {
// TODO: Handle DHCP renew.
Thread dhcpThread = new Thread(new Runnable() {
public void run() {
...
DhcpResults dhcpResults = new DhcpResults();
// TODO: Handle DHCP renewals better.
// In general runDhcp handles DHCP renewals for us, because
// the dhcp client stays running, but if the renewal fails,
// we will lose our IP address and connectivity without
// noticing.
//通过这个函数call到jni之后,最后run /system/bin/dhcpcd
if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
// set our score lower than any network could go
// so we get dropped.
mFactory.setScoreFilter(-1);
return;
}
不知道是不是dhcpcd本身的问题,这段code其实不是稳定,超时拿不到ip的现象经常可以遇到。只能在这里多加几次try runDhcp。
android N新的拿IP的机制
android N不要了runDhcpcd(),而是通过DhcpClient,这个是android M引入的wifi那边另外一种获得ip的方式,DhcpClient是通过framework发送dhcpcd协议的UDP请求包直接去拿IP,不再使用开源的dhcpcd。在调用DhcpClient的基础之前,google还用了一个状态机IpManager来管理dhcpcd成功还是失败等状态,将ip赋值给IpConfiguration和LinkProperties传递到上层的framework。还有就是加入ipv6的支持,不过ipv6的部分目前还没做好。
//EthernetNetworkFactory.java (frameworks\opt\net\ethernet\java\com\android\server\ethernet)
final Thread ipProvisioningThread = new Thread(new Runnable() {
public void run() {
if (DBG) {
Log.d(TAG, String.format("starting ipProvisioningThread(%s): mNetworkInfo=%s",
mIface, mNetworkInfo));
}
LinkProperties linkProperties;
IpConfiguration config = mEthernetManager.getConfiguration();
if (config.getIpAssignment() == IpAssignment.STATIC) {
if (!setStaticIpAddress(config.getStaticIpConfiguration())) {
// We've already logged an error.
return;
}
linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);
} else {
mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
WaitForProvisioningCallback ipmCallback = new WaitForProvisioningCallback() {
@Override
public void onLinkPropertiesChange(LinkProperties newLp) {
synchronized(EthernetNetworkFactory.this) {
if (mNetworkAgent != null && mNetworkInfo.isConnected()) {
mLinkProperties = newLp;
mNetworkAgent.sendLinkProperties(newLp);
}
}
}
};
synchronized(EthernetNetworkFactory.this) {
stopIpManagerLocked();
//IPManger,用这个代替之前的runDhcpcd()
mIpManager = new IpManager(mContext, mIface, ipmCallback);
if (config.getProxySettings() == ProxySettings.STATIC ||
config.getProxySettings() == ProxySettings.PAC) {
mIpManager.setHttpProxy(config.getHttpProxy());
}
final String tcpBufferSizes = mContext.getResources().getString(
com.android.internal.R.string.config_ethernet_tcp_buffers);
if (!TextUtils.isEmpty(tcpBufferSizes)) {
mIpManager.setTcpBufferSizes(tcpBufferSizes);
}
final ProvisioningConfiguration provisioningConfiguration =
mIpManager.buildProvisioningConfiguration()
.withProvisioningTimeoutMs(0)
.build();
//start
mIpManager.startProvisioning(provisioningConfiguration);
}
//通过callback去拿到新的IP
linkProperties = ipmCallback.waitForProvisioning();
if (linkProperties == null) {
Log.e(TAG, "IP provisioning error");
// set our score lower than any network could go
// so we get dropped.
mFactory.setScoreFilter(-1);
synchronized(EthernetNetworkFactory.this) {
stopIpManagerLocked();
}
return;
}
}
IpManager
IpManager,是wifi和Ethernet都会用到。把它定义为获取ip的管理器好了。
1.构造函数
public IpManager(Context context, String ifName, Callback callback)
throws IllegalArgumentException {
this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)));
}
/**
* An expanded constructor, useful for dependency injection.
*/
public IpManager(Context context, String ifName, Callback callback,
INetworkManagementService nwService) throws IllegalArgumentException {
super(IpManager.class.getSimpleName() + "." + ifName);
mTag = getName();
mContext = context;
//网口的名字,eth0 or wlan0
mInterfaceName = ifName;
mClatInterfaceName = CLAT_PREFIX + ifName;
mCallback = new LoggingCallbackWrapper(callback);
//NetworkManagementService对象,可以对Interface做一些操作
mNwService = nwService;
//检测Interface的状态变化
mNetlinkTracker = new NetlinkTracker(
mInterfaceName,
new NetlinkTracker.Callback() {
@Override
public void update() {
sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED);
}
}) {
@Override
public void interfaceAdded(String iface) {
super.interfaceAdded(iface);
if (mClatInterfaceName.equals(iface)) {
mCallback.setNeighborDiscoveryOffload(false);
}
}