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. 定制启动脚本(如果不需要开机自动执行,该步骤可以省略)