一、需求描述
** WiFi上局域网,以太网上外网,只能这样,测试同时打开,先打开以太网再打开wifi,或者先打开wifi再 ,打开以太网都可以同时获取IP wifi测试连接手机热点,笔记本再连接wifi热点测试局域网连接,以太网直接接路由ping外网**
二、实现方案
diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java
b/service/java/com/android/server/wifi/WifiNetworkFactory.java
index 4b5866b..7a1495e 100644
--- a/service/java/com/android/server/wifi/WifiNetworkFactory.java
+++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java
@@ -80,7 +80,7 @@ import java.util.Set;
public class WifiNetworkFactory extends NetworkFactory {
private static final String TAG = "WifiNetworkFactory";
@VisibleForTesting
- private static final int SCORE_FILTER = 60;
+ private static final int SCORE_FILTER = 80;
@VisibleForTesting
public static final int CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS = 20 * 1000; // 20
seconds
@VisibleForTesting
diff --git a/java/com/android/server/ethernet/EthernetNetworkFactory.java
b/java/com/android/server/ethernet/EthernetNetworkFactory.java
index f70e885..8d9f17c 100644
--- a/java/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/java/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -395,7 +395,7 @@ public class EthernetNetworkFactory extends NetworkFactory {
new TransportInfo(ConnectivityManager.TYPE_BLUETOOTH, 69));
// WifiNetworkFactory.SCORE_FILTER / NetworkAgent.WIFI_BASE_SCORE
sTransports.put(NetworkCapabilities.TRANSPORT_WIFI,
- new TransportInfo(ConnectivityManager.TYPE_WIFI, 60));
+ new TransportInfo(ConnectivityManager.TYPE_WIFI, 80));
// TelephonyNetworkFactory.TELEPHONY_NETWORK_SCORE
sTransports.put(NetworkCapabilities.TRANSPORT_CELLULAR,
new TransportInfo(ConnectivityManager.TYPE_MOBILE, 50));
diff --git a/services/core/java/com/android/server/ConnectivityService.java
b/services/core/java/com/android/server/ConnectivityService.java
index e5fddef..8758252 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -238,11 +238,13 @@ public class ConnectivityService extends
IConnectivityManager.Stub
private static final String REQUEST_ARG = "requests";
private static final boolean DBG = true;
- private static final boolean DDBG = Log.isLoggable(TAG, Log.DEBUG);
测试
- private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
+ private static final boolean DDBG = true;//Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean VDBG = true;//Log.isLoggable(TAG, Log.VERBOSE);
private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
+ private static final boolean ENABLE_NETWORK_COEXIST = true;
+
/**
* Default URL to use for {@link #getCaptivePortalServerUrl()}. This should not be
changed
* by OEMs for configuration purposes, as this value is overridden by
@@ -6108,7 +6110,23 @@ public class ConnectivityService extends
IConnectivityManager.Stub
break;
}
}
- nai.asyncChannel.disconnect();
+ if (ENABLE_NETWORK_COEXIST) {
+ log("Skip teardownUnneededNetwork: " + nai.name ());
+ if(nai.getCurrentScore()>0){
+ try{
+ mNMS.removeInterfaceFromNetwork(nai.linkProperties.getInterfaceName(),
+nai.network.netId);
+ mNMS.addInterfaceToLocalNetwork(nai.linkProperties.getInterfaceName(),
+nai.linkProperties.getRoutes());
+ mLegacyTypeTracker.add(nai.networkInfo.getType(),nai);
+ }catch(RemoteException e){
+ Log.e(TAG,"Faided to add iface to local network" + e);
+ }
+ }
+
+ }else{
+ nai.asyncChannel.disconnect();
+ }
}
三、测试验证:
3.1 先连接Ethernet,然后连接WiFi
这种场景,可以看出WiFi对应的wlan0有获取到对应的IP,但是ping 网关ping不通。
1|Mate:/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope: Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 TX bytes:0
eth0 Link encap:Ethernet HWaddr 0a:e0:4c:46:27:12 Driver r8152
inet addr:192.168.101.99 Bcast:192.168.101.255 Mask:255.255.255.0
inet6 addr: fe80::cfaf:977b:cb68:4fdd/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1985 errors:0 dropped:0 overruns:0 frame:0
TX packets:1989 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:220112 TX bytes:172517
wlan0 Link encap:Ethernet HWaddr 00:c5:35:4a:7b:f9 Driver unisoc_wifi
inet addr:192.168.49.123 Bcast:192.168.49.255 Mask:255.255.255.0
inet6 addr: fe80::4adf:3897:276e:9bf0/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:38 errors:0 dropped:0 overruns:0 frame:0
TX packets:50 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2938 TX bytes:4511
ping网关ping 不通。提示Time to live exceeded
Mate:/ # ping 192.168.49.1
PING 192.168.49.1 (192.168.49.1) 56(84) bytes of data.
From 192.168.1.1: icmp_seq=1 Time to live exceeded
From 192.168.1.1: icmp_seq=2 Time to live exceeded
From 192.168.1.1: icmp_seq=3 Time to live exceeded
通过ip rule查看,并没有经过wlan0到达网关的路由,因此我们需要增加路由配置,使数据包目的地址为 192.168.49.0/24 的数据,使用路由表main。
Mate:/ # ip rule
0: from all lookup local
10000: from all fwmark 0xc0000/0xd0000 lookup legacy_system
10500: from all iif lo oif eth0 uidrange 0-0 lookup eth0
10500: from all iif lo oif wlan0 uidrange 0-0 lookup wlan0
13000: from all fwmark 0x10063/0x1ffff iif lo lookup local_network
13000: from all fwmark 0x10065/0x1ffff iif lo lookup eth0
13000: from all fwmark 0x10066/0x1ffff iif lo lookup wlan0
14000: from all iif lo oif eth0 lookup eth0
14000: from all iif lo 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 iif lo lookup eth0
19000: from all fwmark 0x66/0x1ffff iif lo lookup wlan0
22000: from all fwmark 0x0/0xffff iif lo lookup eth0
32000: from all unreachable
手动增加路由配置如下:
Mate:/ # ip rule add to 192.168.49.0/24 table main
Mate:/ # ip rule
0: from all lookup local
9999: from all to 192.168.49.0/24 lookup main
10000: from all fwmark 0xc0000/0xd0000 lookup legacy_system
10500: from all iif lo oif eth0 uidrange 0-0 lookup eth0
10500: from all iif lo oif wlan0 uidrange 0-0 lookup wlan0
13000: from all fwmark 0x10063/0x1ffff iif lo lookup local_network
13000: from all fwmark 0x10065/0x1ffff iif lo lookup eth0
13000: from all fwmark 0x10066/0x1ffff iif lo lookup wlan0
14000: from all iif lo oif eth0 lookup eth0
14000: from all iif lo 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 iif lo lookup eth0
19000: from all fwmark 0x66/0x1ffff iif lo lookup wlan0
22000: from all fwmark 0x0/0xffff iif lo lookup eth0
32000: from all unreachable
可以发现通过ip rule增加了一行9999: from all to 192.168.49.0/24 lookup main,此时在ping 网关已经可以ping通了,并且外网使用的ethernet。
Mate:/ # ping 192.168.49.1
PING 192.168.49.1 (192.168.49.1) 56(84) bytes of data.
64 bytes from 192.168.49.1: icmp_seq=1 ttl=64 time=4.76 ms
64 bytes from 192.168.49.1: icmp_seq=2 ttl=64 time=1.97 ms
64 bytes from 192.168.49.1: icmp_seq=3 ttl=64 time=3.94 ms
64 bytes from 192.168.49.1: icmp_seq=4 ttl=64 time=2.07 ms
//外网使用ethernet
Mate:/ # ping -I eth0 www.baidu.com
PING www.a.shifen.com (14.119.104.189) from 192.168.101.99 eth0: 56(84) bytes of data.
64 bytes from 14.119.104.189: icmp_seq=1 ttl=54 time=33.2 ms
64 bytes from 14.119.104.189: icmp_seq=2 ttl=54 time=34.0 ms
64 bytes from 14.119.104.189: icmp_seq=3 ttl=54 time=37.0 ms
//默认使用ethernet进行上外网
Mate:/ # ping -vadDR www.baidu.com
PING www.a.shifen.com (14.119.104.189) 56(124) bytes of data.
[1681441568.924344] 64 bytes from 14.119.104.189: icmp_seq=1 ttl=54 time=100 ms
RR: 192.168.101.99
192.168.1.15
61.150.12.228
10.224.21.2
1.85.253.94
202.97.98.213
113.96.4.161
85.96.135.219.broad.fs.gd.dynamic.163data.com.cn (219.135.96.85)
14.29.117.129
Mate:/ # ip role
192.168.49.0/24 dev wlan0 proto kernel scope link src 192.168.49.123
192.168.101.0/24 dev eth0 proto kernel scope link src 192.168.101.99
2、先连接WiFi,在连接Ethernet
此时默认还是Ethernet使用外网,WiFi进行局域网内通信。
Mate:/ # ping -I eth0 www.baidu.com
PING www.a.shifen.com (14.119.104.254) from 192.168.101.99 eth0: 56(84) bytes of data.
64 bytes from 14.119.104.254: icmp_seq=1 ttl=54 time=37.8 ms
64 bytes from 14.119.104.254: icmp_seq=2 ttl=54 time=33.3 ms
64 bytes from 14.119.104.254: icmp_seq=3 ttl=54 time=32.8 ms
Mate:/ # ping -vadDR www.baidu.com
PING www.a.shifen.com (14.119.104.254) 56(124) bytes of data.
[1681441793.209947] 64 bytes from 14.119.104.254: icmp_seq=1 ttl=54 time=123 ms
RR: 192.168.101.99
192.168.1.15
61.150.12.228
10.224.21.6
117.36.240.218
202.97.74.66
113.96.4.121
121.14.14.137
14.29.117.149
四、使用CODE增加路由策略
整体思路:在rc文件中根据属性触发一个服务执行sh脚本来添加对应的路由策略,在连接WiFi获取Ip过程中设置该属性,添加策略。
#/system/core/rootdir/init.rc
#screenmirro
on property:sys.xxx.screenmirro=1
start screenmirro
service screenmirro /system/bin/sh /system/bin/clientnetwork.sh
class late_start
user root
group root
disabled
oneshot
seclabel u:r:shell:s0
脚本内容如下:
#!/system/bin/sh
IP1="192.168.49.2/24"
IP2="192.168.49.0/24"
IP_RULE_LIST=`ip rule list`
RULE_P2P="from all to 192.168.49.0/24 lookup main"
ip add add $IP2 dev wlan0
ip route add $IP2 dev wlan0
if [[ $IP_RULE_LIST == *$RULE_P2P* ]];
then
echo "already exist: $RULE_P2P"
else
ip rule add to $IP2 table main
fi
#清除防火墙策略
#iptables -F
exit 0
在WiFi连接上,获取Ip的过程中,设置sys.xxx.screenmirro属性为1。
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
Slog.w(TAG, "WifiManager.NETWORK_STATE_CHANGED_ACTION");
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (info.getState().equals(NetworkInfo.State.DISCONNECTED)) {
Slog.i(TAG, "disconnected");
isWifiConnected = false;
if (mWifiConnectListener != null) {
mWifiConnectListener.onDisconnect();
}
} else if (info.getState().equals(NetworkInfo.State.CONNECTED)) {
final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
isWifiConnected = true;
Slog.i(TAG, "connected: " + wifiInfo.getSSID());
if (mWifiConnectListener != null) {
mWifiConnectListener.onConnected();
}
} else {
NetworkInfo.DetailedState state = info.getDetailedState();
if (state == state.CONNECTING) {
Slog.i(TAG, "wifi connect...");
} else if (state == state.AUTHENTICATING) {
Slog.i(TAG, "authenticating...");
} else if (state == state.OBTAINING_IPADDR) {
Slog.i(TAG, "obtaing ip addr...");
//增加路由,确保wifi和ethernet可以共存
SystemProperties.set("sys.dten.screenmirro","1");
} else if (state == state.FAILED) {
Slog.i(TAG, "connect failed");
isWifiConnected = false;
if (mWifiConnectListener != null) {
mWifiConnectListener.onConnectFaild();
}
}
}
}
}
};