现象
在客户反馈网络问题的时候,发现一个很奇怪的,DHCP情况下,莫名其妙的断网,日志如下
D/dhcp ( 1767): ===========DHCP stop===interface:eth0=======daemon_cmd:dhcpcd_eth0
D/dhcp ( 1767): ====func:dhcp_do_request=====
D/dhcp ( 1767): ===========DHCP==========daemon_cmd:dhcpcd_eth0:-f /system/etc/dhcpcd/dhcpcd.conf -h android-ba7b6b8cf5f0b590 eth0
D/dhcp ( 1767): ===========DHCP==========daemon_prop_name:init.svc.dhcpcd_eth0, desired_status:running
D/dhcp ( 1767): 1====DHCP=====Timed out waiting for dhcpcd to start
D/NetUtils( 1767): dhcp_do_request failed : eth0 (new)
E/Ethernet( 1767): DHCP request error:Timed out waiting for dhcpcd to start
D/dhcp ( 1767): ===========DHCP stop===interface:eth0=======daemon_cmd:dhcpcd_eth0
D/dhcp ( 1767): ====func:dhcp_do_request=====
D/dhcp ( 1767): ===========DHCP==========daemon_cmd:dhcpcd_eth0:-f /system/etc/dhcpcd/dhcpcd.conf -h android-ba7b6b8cf5f0b590 eth0
D/dhcp ( 1767): ===========DHCP==========daemon_prop_name:init.svc.dhcpcd_eth0, desired_status:running
D/dhcp ( 1767): 1====DHCP=====Timed out waiting for dhcpcd to start
D/NetUtils( 1767): dhcp_do_request failed : eth0 (new)
E/Ethernet( 1767): DHCP request error:Timed out waiting for dhcpcd to start
D/dhcp ( 1767): ===========DHCP stop===interface:eth0=======daemon_cmd:dhcpcd_eth0
D/dhcp ( 1767): ====func:dhcp_do_request=====
D/dhcp ( 1767): ===========DHCP==========daemon_cmd:dhcpcd_eth0:-f /system/etc/dhcpcd/dhcpcd.conf -h android-ba7b6b8cf5f0b590 eth0
D/dhcp ( 1767): ===========DHCP==========daemon_prop_name:init.svc.dhcpcd_eth0, desired_status:running
超时之后,无论如何网络都不正常,郁闷了好久,最后只能硬着硬皮翻看framework代码,详细的代码分析可以参考别人的博客
https://blog.csdn.net/iampisfan/article/details/51043151
https://blog.csdn.net/IT_xiao_bai0516/article/details/123132036
https://blog.csdn.net/luzze__123/article/details/120826232
https://www.cnblogs.com/schips/p/android_api-property_get-and-property_set.html
我只是总结一下
1 android framework负责在开关网络是启动或者关闭dhcpcd程序,这个程序是开源程序,他的作用就是用来跟dhcp服务器交互的。
2 通信的结果是通过prop机制来通信的,用getprop | grep dhcp 就可以看到他们的通信结果。
3 framework 跟dhcpcd通信是单向的,单向的,单向的!
于是这样就会在某些网络里出现出现奇奇怪怪的问题:
1 dhcpcd 超时退出了,这个为什么出现不太清楚,是在客户环境里出现的,
可以这样确认
shell@sabresd_6dq:/ # ps | grep "dhcp"
dhcp 2222 2221 1032 476 c0141530 402178c4 S /system/bin/dhcpcd
这是正常的样子,我当时没有这个dhcpcd程序了,继续抓日志
130|shell@sabresd_6dq:/ # logcat -s dhcpcd -v time
--------- beginning of /dev/log/system
--------- beginning of /dev/log/main
I/dhcpcd ( 2160): dhcpcd[2162]: timed out
I/dhcpcd ( 2160): dhcpcd terminated by exit(1)
I/dhcpcd ( 3032): dhcpcd[3033]: version 5.5.6 starting
I/dhcpcd ( 3032): dhcpcd[3033]: eth0: broadcasting for a lease
I/dhcpcd ( 3032): dhcpcd[3033]: timed out
I/dhcpcd ( 3032): dhcpcd terminated by exit(1)
I/dhcpcd ( 3799): dhcpcd[3800]: version 5.5.6 starting
I/dhcpcd ( 3799): dhcpcd[3800]: eth0: broadcasting for a lease
I/dhcpcd ( 3799): dhcpcd[3800]: eth0: offered 192.168.1.201 from 192.168.1.1
I/dhcpcd ( 3799): dhcpcd[3800]: eth0: acknowledged 192.168.1.201 from 192.168.1.1
I/dhcpcd ( 3799): dhcpcd[3800]: eth0: leased 192.168.1.201 for 300 seconds
I/dhcpcd ( 4657): dhcpcd[4658]: version 5.5.6 starting
I/dhcpcd ( 4657): dhcpcd[4658]: eth0: rebinding lease of 192.168.1.201
I/dhcpcd ( 4657): dhcpcd[4658]: eth0: broadcasting for a lease
I/dhcpcd ( 4657): dhcpcd[4658]: timed out
I/dhcpcd ( 4657): dhcpcd terminated by exit(1)
可以看到是超时退出,我只能先解决掉超时的问题,解决方案如下,修改超时时间
vi device/fsl/imx6/etc/init.rc
service dhcpcd_eth0 /system/bin/logwrapper /system/bin/dhcpcd -ABKL -t 0
-t 0 代表了永远不超时
这样一改,就不用超时退出了。
2 但是这样修改之后,所有的网络信息都是正常的,网络通信也是正常的,但是上层页面看不到网络信息,WTF!客户很急的,最后修改framework文件
vi ./frameworks/base/core/java/android/net/EthernetDataTracker.java
//add by wgd 20220727
import android.os.Build;
import java.lang.reflect.Method;
import java.util.Timer;
import java.util.TimerTask;
//end
//txr 20220727 check dhcp need update
private String getDevicePrep(String prep) throws Exception {
String serial = "unknown";
Class<?> clazz = Class.forName("android.os.Build");
Class<?> paraTypes = Class.forName("java.lang.String");
Method method = clazz.getDeclaredMethod("getString", paraTypes);
if (!method.isAccessible()) {
method.setAccessible(true);
}
serial = (String) method.invoke(new Build(), prep);
return serial;
}
private String lastPropVal = "" ;
private Timer dhcpTimer;
public void openDhcpCheckTimer(){
if (dhcpTimer == null){
dhcpTimer = new Timer();
}else {
stopDhcpCheckTimer();
dhcpTimer = new Timer();
}
dhcpTimer.schedule(new TimerTask() {
@Override
public void run() {
Log.d(TAG ,"the timer is run<------------");
String propVal = "";
try{
String propName = "dhcp."+mIface+".result" ;
propVal = getDevicePrep(propName);
Log.d(TAG, "**************checkDhcpUpdate propName " + propName + " " + "lastPropVal " + lastPropVal + " " + "propVal " + propVal);
if( !(lastPropVal.equals("ok"))&& propVal.equals("ok") && !(mNetworkInfo.getDetailedState().equals(DetailedState.CONNECTED)) ){
Log.d(TAG, "**************update dhcp " + mIface);
mNetworkInfo.setIsAvailable(true);
mLinkProperties.setInterfaceName(mIface);
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
sendEthStateChangedBroadcast(ETHER_STATE_CONNECTED);
}
lastPropVal = propVal ;
}catch(Exception e){
e.printStackTrace();
}
}
},10,10000);
}
private void stopDhcpCheckTimer(){
if(dhcpTimer!=null){
dhcpTimer.cancel();
dhcpTimer = null;
}
}
//txr end
public boolean teardown() {
mTeardownRequested.set(true);
NetworkUtils.stopDhcp(mIface);
//txr 20220728 stop check dhcp update
stopDhcpCheckTimer();
return true;
}
public boolean reconnect() {
if (mLinkUp) {
int iface_state = getEthernetIfaceState();
int carrier_state = getEthernetCarrierState();
if((iface_state == ETHER_IFACE_STATE_UP) &&
(carrier_state == 1)){
mTeardownRequested.set(false);
runDhcp();
//txr add check hdcp update
openDhcpCheckTimer();
}
}
return mLinkUp;
}
先添加一个定时器,去看dhcp.eth0.result是不是变化了,如果变化了 ,就强制上报一个网络信息。
虽然这样问题暂时解决了,但是还是想不通为什么在我们的dhcp环境下没什么问题,但是在客户环境里,竟然30s都获取不到dhcp的ip,郁闷,看各位有什么更好的方案?