Android WiFi和Ethernet共存

一、需求描述

** 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();
                        }

                    }
                }
            }
        }
    };

你可能感兴趣的:(Android无线网络通信,android,java,开发语言,网络协议,网络)