Bootstrap

Android以太网和WIFI完美共存

Android以太网和WIFI完美共存

目前安卓设备主要为移动设备,安卓系统相应针对移动设备特性做了一些优化。考虑移动设备尽量降低功耗的需求,所以在网络部分设计了评分机制,(数据连接50,WIFI60,蓝牙69,网线70),当有高分网络可用,就会释放低评分网络的资源,该机制设计是非常合理的。

 

1. 修改安卓网络评分机制

安卓系统关于网络评分相关代码位置:

frameworks/base/core/java/android/net/NetworkFactory.java

 

去掉红字标识部分,即不再根据网络评分来加载和释放网络资源。

private void evalRequest(NetworkRequestInfo n) {

if (n.requested == false && n.score < mScore && n.request.networkCapabilities.satisfiedByNetworkCapabilities( mCapabilityFilter) && acceptRequest(n.request, n.score)) {

      needNetworkFor(n.request, n.score);

      n.requested = true;

} else if (n.requested == true &&

    (n.score > mScore ||n.request.networkCapabilities.satisfiedByNetworkCapabilities(

    mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {

        releaseNetworkFor(n.request);

        n.requested = false;

    }

}

 

去掉评分相关部分之后代码如下:

private void evalRequest(NetworkRequestInfo n) {

if (n.requested == false  && n.request.networkCapabilities.satisfiedByNetworkCapabilities( mCapabilityFilter) && acceptRequest(n.request, n.score)) {

      needNetworkFor(n.request, n.score);

      n.requested = true;

} else if (n.requested == true &&

    (n.request.networkCapabilities.satisfiedByNetworkCapabilities(

    mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {

        releaseNetworkFor(n.request);

        n.requested = false;

    }

}

修改评分机制,修改完之后发现安卓系统内可以同时存在以太网,WIFI和4g网络但是网络还是不通,是因为安卓的路由表机制导致,所以还要根据第二步修改路由表。

 

2. 修改路由表

修改路由表优先级命令如下,修改完之后以太网,wifi,4g可完美共存

busybox ip rule add from all lookup main pref 9000

至此其实已经完美解决了以太网和wifi共存的问题,可以尝试ping内网和外网,插拔网线,开关wifi,4g等各种操作,最终网络总能恢复正常。但是鉴于修改路由表使用的是命令行命令,每次开机都需要执行该指令来修改main路由表优先级,所以如果想要一劳永逸,就需要继续参考第3步,定制启动脚本,把修改路由表的指令放到启动脚本执行,就能完美解决了。定制启动脚本具体方法参考第3步骤,至于以下内容简单介绍了路由表查询,修改的缘由,感兴趣的小伙伴可以仔细阅读,不感兴趣也可以直接略过,直接查看第3步骤,定制启动脚本。

 

ip rule list 

打印所有路由表:

 

nanopc-t4:/ $ ip rule list

0:      from all lookup local

10000:  from all fwmark 0xc0000/0xd0000 lookup legacy_system

10500:  from all oif eth0 uidrange 0-0 lookup eth0

10500:  from all oif wlan0 uidrange 0-0 lookup wlan0

13000:  from all fwmark 0x10063/0x1ffff lookup local_network

13000:  from all fwmark 0x10065/0x1ffff lookup eth0

13000:  from all fwmark 0x10066/0x1ffff lookup wlan0

14000:  from all oif eth0 lookup eth0

14000:  from all oif wlan0 lookup wlan0

15000:  from all fwmark 0x0/0x10000 lookup legacy_system

16000:  from all fwmark 0x0/0x10000 lookup legacy_network

17000:  from all fwmark 0x0/0x10000 lookup local_network

19000:  from all fwmark 0x65/0x1ffff lookup eth0

19000:  from all fwmark 0x66/0x1ffff lookup wlan0

22000:  from all fwmark 0x0/0xffff lookup wlan0

23000:  from all fwmark 0x0/0xffff uidrange 0-0 lookup main

32000:  from all unreachable

 

0~32000代表优先级,0优先级最高,安卓路由表规则较复杂,路由表由系统自动生成,根据网络类型不同自动生成路由表,如以太网路由表,wifi路由表等。所以,即便以太网和wifi可以共存,

但是系统默认还是优先走以太网路由表,路由表规则示例如下:

 

ip route list table eth0

打印路由表eth0规则:

 

路由规则:

nanopc-t4:/ $ ip route list table eth0

default via 192.168.135.1 dev eth0  proto static

192.168.135.0/24 dev eth0  proto static  scope link

 

nanopc-t4:/ $ ip route list table wlan0

default via 12.12.81.1 dev wlan0  proto static

12.12.81.0/24 dev wlan0  proto static  scope link

 

eth0 和 wlan0这两个路由表只有其中一个会生效,所以外网和内网同时只有一个能正常工作。

 

为了解决这个问题,我们需要构造一个如下路由表:

12.12.81.0/24 dev wlan0  proto kernel  scope link  src 12.12.81.172

192.168.137.0/24 dev eth0  proto kernel  scope link  src 192.168.137.234

我们可以通过命令修改路由表,可以在系统启动之后修改路由表的表项来达到我们的目的,但是存在的问题是路由表是动态生成的,每次网络变化路由表也会跟随动态变化,比如说网络断开了,之前存在的路由表项会默认被清掉,但是重连之后他不会自动生效,需要再次手动使能。所以要求我们能监测并捕获网络状态变化,动态修改路由表,这个工作量很大,需要的规则也很复杂,经过一段时间摸索,发下 main路由表这张低优先级路由表包含所有我们想要的路由表项,并且能根据网络状态变化动态变化,正好满足我们的需要,所以问题就变得简单了,我们只需要修改一下main路由表的优先级,把他调到最高,这样就完美解决这个问题。

命令如下;

busybox ip rule add from all lookup main pref 9000

 

修改之后的路由表如下:

nanopc-t4:/ # ip ru ls

0:      from all lookup local

9000:   from all lookup main

10000:  from all fwmark 0xc0000/0xd0000 lookup legacy_system

10500:  from all oif eth0 uidrange 0-0 lookup eth0

10500:  from all oif wlan0 uidrange 0-0 lookup wlan0

13000:  from all fwmark 0x10063/0x1ffff lookup local_network

13000:  from all fwmark 0x10065/0x1ffff lookup eth0

13000:  from all fwmark 0x10066/0x1ffff lookup wlan0

14000:  from all oif eth0 lookup eth0

14000:  from all oif wlan0 lookup wlan0

15000:  from all fwmark 0x0/0x10000 lookup legacy_system

16000:  from all fwmark 0x0/0x10000 lookup legacy_network

17000:  from all fwmark 0x0/0x10000 lookup local_network

19000:  from all fwmark 0x65/0x1ffff lookup eth0

19000:  from all fwmark 0x66/0x1ffff lookup wlan0

22000:  from all fwmark 0x0/0xffff lookup wlan0

23000:  from all fwmark 0x0/0xffff uidrange 0-0 lookup main

32000:  from all unreachable

按照我们的思路设置后确实完美解决了我们的问题,那么下一步就是让这条语句开机自动执行(定制开机启动脚本)

 

3. 定制启动脚本

 

3. 1 构造启动脚本

ethernet_wifi.sh

 

启动脚本内容如下:

#!/system/bin/sh

echo "modify route table"

busybox ip rule add from all lookup main pref 9000

 

3. 2 copy启动脚本到android镜像

修改vendor/rockchip/common/wifi/wifi.mk增加如下:

$(CUR_PATH)/wifi/ethernet_wifi.sh:$(TARGET_COPY_OUT_VENDOR)/bin/ethernet_wifi.sh

 

3.3 增加启动语句

在启动文件中修改device/rockchip/rk3399/init.rk3399.rc

on property:sys.boot_completed=1

start ethernet_wifi

 

service ethernet_wifi /system/bin/sh /vendor/bin/ethernet_wifi.sh

class main

user root

group root

disabled

oneshot

seclabel u:r:ethernet_wifi:s0

完成之后镜像烧写到android板卡试运行,如果出现权限问题,参考以下4,5方法。

 

3.4 生成权限文件

adb connect 192.168.1.128

adb shell "dmesg | grep avc" > avc_log.txt

external/selinux/prebuilts/bin/audit2allow -i avc_log.txt > avc.te

在avc.te中找到ethernet_wifi字段:seclabel u:r:ethernet_wifi:s0 找到相应的权限问题

 

3.5 构造权限文件放到对应目录

构造权限文件device/rockchip/common/sepolicy/ethernet_wifi.te

 

总结:

1. 修改评分机制

2. 修改路由表

busybox ip rule add from all lookup main pref 9000

3. 定制启动脚本(如果不需要开机自动执行,该步骤可以省略)

 

;