关于Android系统在开机后无法自动连接以太网的问题

来源:互联网 发布:大华行知实验幼儿园 编辑:程序博客网 时间:2024/05/17 21:48

Android系统版本:4.4

以太网卡:RTL8152B


最近有个客户说想要在android板上加入以太网功能,就在淘宝上先买了一个RTL8152的USB网卡(RTL8152本身就是USB接口的),就着手开始了移植工作


其实Android4.4已经支持以太网了,如果手上的android源码不支持以太网功能的话,就要自己移植代码,方法的话网上一抓一大把,我这里就不再赘述了


我需要做的只是在linux内核中将RTL8152的驱动加进去,将网卡接入板子的USB口,就可以开机看效果了


果然!果然!果然!果然!果然!果然!


开机之后发现以太网无法连接,就算执行了netcfg eth0 up dhcp也不行。

很奇怪的是执行了netcfg eth0 up dhcp这句代码后,使用ifconfig看网卡信息可以发现网卡已经自动获取到了ip地址,而且也可以ping通外网,可是使用浏览器却提示无法连接网络


我还尝试了将以太网连接的优先级设为0(本身为9),也还是不行


查看logcat发现在以太网卡启动的时候,有如下打印:

I/SystemServer(  501): Connectivity ServiceI/ethernet(  501): ==>android_net_ethernet_initEthernetNativeD/ConnectivityService(  501): ConnectivityService starting upD/ConnectivityService(  501): wifiOnly=falseD/ConnectivityService(  501): *******netType=wifi,1,1,1,-1,trueD/ConnectivityService(  501): *******netType=ethernet,9,9,0,-1,trueE/ConnectivityService(  501): Ignoring protectedNetwork 10E/ConnectivityService(  501): Ignoring protectedNetwork 11E/ConnectivityService(  501): Ignoring protectedNetwork 12E/ConnectivityService(  501): Ignoring protectedNetwork 14D/ConnectivityService(  501): *******targetNetworkType=1I/EthernetStateTracker(  501): Starts...I/EthernetStateTracker(  501): SuccessI/ethernet(  501): User ask for device name on 0, total:1I/ethernet(  501): Found :eth0V/EthernetService(  501): Ethernet dev enabled 2I/EthernetService(  501): total found 1 net devicesI/EthernetService(  501):  device 0 name eth0I/EthernetService(  501): setEthState from 0 to 2V/EthernetService(  501): Set ethernet mode [Ljava.lang.String;@41af6338 -> dhcpD/NetUtils(  501): android_net_utils_resetConnections in env=0x415a6fb8 clazz=0x8f000019 iface=eth0 mask=0x3I/EthernetService(  501): $$ EthernetService uninited,disable setEthState() call resetInterface()I/EthernetService(  501): $$ resetInterface() will be called in reconnect()V/EthernetService(  501): Trigger the ethernet monitorV/EthernetStateTracker(  501): start pollingD/ConnectivityService(  501): *******targetNetworkType=9I/EthernetStateTracker(  501): start to monitor the Ethernet devicesI/EthernetManager(  501): Init Ethernet ManagerI/EthernetStateTracker(  501): $$ DISABLE startMonitoring call resetInterface()I/EthernetStateTracker(  501): >>>reconnectI/EthernetService(  501): setEthState from 2 to 2I/EthernetStateTracker(  501): $$reconnect call resetInterface()I/EthernetStateTracker(  501): reset device eth0V/AudioFlinger(  156): releaseWakeLock_l() AudioOut_2V/AudioFlinger(  156): thread 0xb36d5008 type 0 TID 557 going to sleepV/AudioFlinger(  156): releaseWakeLock_l() AudioOut_7V/AudioFlinger(  156): releaseWakeLock_l() AudioOut_8V/AudioFlinger(  156): thread 0xb3553008 type 0 TID 558 going to sleepV/AudioFlinger(  156): thread 0xb3412008 type 2 TID 559 going to sleepD/WifiHW  (  501): Unable to unload driver module "dhd": No such file or directoryI/EthernetStateTracker(  501): Force the connection disconnected before configurationD/EthernetStateTracker(  501): setEthState state=false->false event=4I/ethernet(  501): eth0: NEWLINK(16), flags=0X11043( LINK_UP MC RUNNING BC UP)I/ethernet(  501): eth0:16:E/ethernet(  501): netlink_route socket readable: [eth0:16:]I/EthernetStateTracker(  501): report interface is up for eth0D/EthernetStateTracker(  501): eth0 is not up!I/EthernetStateTracker(  501): Old status stackConnected=false HWConnected=falseI/EthernetStateTracker(  501): [EVENT: Ether is up]I/WifiService(  501): WifiService starting up with Wi-Fi disabledD/EthernetService(  501): isEthernetDeviceAdded(eth0) return trueD/EthernetStateTracker(  501): setEthState state=false->false event=5I/EthernetStateTracker(  501): New status, stackConnected=false HWConnected=true mStartingDhcp=falseD/EthernetStateTracker(  501): eth0 is not up!

可以看到以太网的服务是起来了,可是却无法使能eth0(?),其中关键的一句:

D/EthernetStateTracker(  501): eth0 is not up!

引起了我的注意,可是我想先试试别的方法


我又试着在Setting里为以太网设置静态ip,设置完之后发现可以联网,可见是dhcp出了问题

我又在开机状态下插拔了一下网线,发现可以上网了。。。。。


在各种百度GOOGLE无果后我开始自己研究


主要问题:为什么在开机过程中无法启动DHCP分配IP,而是要在开机后再插拔网线才能启动DHCP呢?


这下就要关注这句报错了:

eth0 is not up!


在Android源码的frameworks/base/ethernet/java/android/net/ethernet目录下可以找到EthernetStateTracker.java这个文件,“xxx is not up”就在这里:

private boolean configureInterface(EthernetDevInfo info) throws UnknownHostException {........................if (info.getConnectMode().equals(EthernetDevInfo.ETH_CONN_MODE_DHCP)) {             if(mInterfaceName != null && !mEM.isEthernetDeviceUp(mInterfaceName)) {                 Slog.d(TAG, mInterfaceName + " is not up!");                 return false;             }........................}


发现有个if判断,其中如果
if(mInterfaceName != null && !mEM.isEthernetDeviceUp(mInterfaceName))

为真的话,就会打印xxx is not up然后返回一个false,我试着屏蔽了这个return,发现板子一开机就可以自动联网了,DHCP也开启正常


耶!!!大功告成!!

。。。。。。。。。。。。。

事情当然没有那么简单,如果单单屏蔽这个return的话,系统就会在没有网线接入的情况下不断启动dhcp来自动获取ip,结果当然是失败的。而且系统会在调用失败后不停的继续调用dhcp这个功能,这样做当然是不严谨的。


我将mInterfaceName,EthernetDevInfo.ETH_CONN_MODE_DHCP,mEM.isEthernetDeviceUp(mInterfaceName)这三个参数打印了出来,发现

mInterfaceName = eth0

EthernetDevInfo.ETH_CONN_MODE_DHCP = dhcp

mEM.isEthernetDeviceUp(mInterfaceName) = false


看来问题就出在isEthernetDeviceUp这个方法调用上了


我与正常连接状态下的打印对比了一下,发现mEM.isEthernetDeviceUp(mInterfaceName) = true


接下来就追踪isEthernetDeviceUp方法,发现在frameworks/base/services/java/com/android/server目录下的EthernetService.java文件里:



看来系统判断以太网的状态是通过/sys/class/net/“ifname”/operstat这个设备节点来确定的

ifname是你的网络设备名,一般是eth0,也有可能是eth1


我在板子里输入命令:cat /sys/class/net/eth0/operstate,发现这个节点的状态是"unknown",拔掉网线,状态变为"down",再次插上网线,状态变为"up"

看来系统在开机时无法判断网络使能的情况,只有在系统启动后插拔网线,状态才能被检测到


我认为operstate这个节点保存的是以太网的运行状态,即是说当网线插入时,若禁止以太网功能,此节点的值仍然会变为"down"


而我的板子在系统启动之后operstate的值为"unknown",这就很奇怪了,可能是系统无法正常设置这个节点的值吧。

但是不用担心,在同一目录下还有另一个节点的值可供我们检测网线的插入状态,就是carrier。在网线插入时,carrier的之为1,网线拔出时,carrier的值为0。所以我们可以模仿isEthernetDeviceUp里的判断代码来另外写一个判断:

public boolean isEthernetDeviceUp(String ifname) {    try {        boolean retval = false;        FileReader fr = new FileReader("/sys/class/net/" + ifname +"/operstate");        BufferedReader br = new BufferedReader(fr, 32);        String status = br.readLine();        if (status != null && status.equals("up")) {            Slog.d(TAG, ifname + " status:" + status);            retval = true;        }        else if (status != null && status.equals("down")) {            Slog.d(TAG, ifname + " status:" + status);            retval = false;        }        else {            retval =  false;        }/****************************Add Start****************************/FileReader kFr = new FileReader("/sys/class/net/" + ifname + "/carrier");BufferedReader kBr = new BufferedReader(kFr, 32);String kStatus = kBr.readLine();if(kStatus != null && kStatus.equals("1")) {Slog.d(TAG, DevName[0] + " kStatus:" + kStatus);retval = true;}else if(kStatus != null && kStatus.equals("0")) {Slog.d(TAG, DevName[0] + " kStatus:" + kStatus);retval = false;}else {retval = false;}kBr.close();kFr.close();/****************************Add End****************************/        br.close();        fr.close();        return retval;    } catch (IOException e) {        Slog.d(TAG, "get " + ifname + " status error");        return false;    }}


此时,系统在检测完operstate的值之后就会继续去检测carrier的值,最后返回的结果是检测carrier的结果,大家如果喜欢的话可以将operstate的检测代码段屏蔽掉


这样修改之后系统就可以在启动的过程中就开启以太网功能并使用DHCP去自动获取IP地址,DNS等参数


OK,大功告成!


0 0
原创粉丝点击