版本信息: 
android5.1.1 
Linux version 3.10.49

需求:通过4g访问外网,同时通过wifi访问内网。 
 android系统默认情况下,wifi连网时,4g数据链接会被强制断开,但实际有需要wifi和4g同时上网,为了满足这个要求,需要修改android的网络管理机制。 
 首先实现wifi连网时,不让4g数据链接被强制断开: 
 修改  frameworks/base/services/core/java/com/android/server/ConnectivityService.java

private void teardownUnneededNetwork(NetworkAgentInfo nai) {
        for (int i = 0; i < nai.networkRequests.size(); i++) {
            NetworkRequest nr = nai.networkRequests.valueAt(i);
            // Ignore listening requests.
            if (!isRequest(nr)) continue;
            loge("Dead network still had at least " + nr);
            break;
        }
        //nai.asyncChannel.disconnect();
    }
把nai.asyncChannel.disconnect(); 行mark掉。
这样wifi连网,4g数据链接不会被强制断开了。

  $ netcfg 
rmnet0 UP 0.0.0.0/0 0x00000041 00:00:00:00:00:00 
r_rmnet_data8 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
r_rmnet_data7 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
r_rmnet_data5 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
r_rmnet_data6 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
r_rmnet_data4 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
r_rmnet_data3 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
r_rmnet_data1 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
r_rmnet_data2 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
r_rmnet_data0 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
rmnet_data4 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
rmnet_data2 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
rmnet_data3 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
rmnet_data1 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
rmnet_data0 UP 10.66.94.93/30 0x00000041 00:00:00:00:00:00 
rmnet_data7 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
rmnet_data5 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
rmnet_data6 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00 
wlan0 UP 192.168.10.10/24 0x00001043 34:87:3d:31:e4:77 
sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00 
p2p0 UP 0.0.0.0/0 0x00001003 36:87:3d:31:e4:77 
lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00 
dummy0 DOWN 0.0.0.0/0 0x00000082 d6:d1:38:38:ed:c8

  但此时,网络访问默认还是走wifi通道,把wifi AP与外网断开,ping下192.168.10.1可以ping通,但www.baidu.com会发现ping不通, 
  指定network,再ping 
  ping -I rmnet_data0 www.baidu.com   
  会发现可以ping通,说明此时wifi和4g都已经连上网了。 

  APP程序可以通过setProcessDefaultNetwork把进程和network绑定来访问特定网络。

https://yq.aliyun.com/articles/341803

/*修改外置摄像头只能通过wifi上网  begin 20180619*/
import android.net.ConnectivityManager; 

import android.content.Context; 

import android.net.NetworkRequest; 

import android.net.NetworkCapabilities; 

import android.net.Network; 

/*修改外置摄像头只能通过wifi上网  end 20180619*/ 

/*修改外置摄像头只能通过wifi上网  begin 20180619*/
 //设置该APP只能通过wifi传输数据
 public void setwifiNet(Context context) {
 ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
 Context.CONNECTIVITY_SERVICE);
 NetworkRequest.Builder req = new NetworkRequest.Builder();
 //req.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
 // 设置指定的网络传输类型 wifi
 req.addTransportType(NetworkCapabilities.TRANSPORT_WIFI );
 cm.requestNetwork(req.build(), new ConnectivityManager.NetworkCallback() {


 @Override
 public void onAvailable(Network network) {
 try {
 /*if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
 ConnectivityManager.setProcessDefaultNetwork(network);
 } else {
 connectivityManager.bindProcessToNetwork(network);
 }*/
 //if (Build.VERSION.SDK_INT >= 23) {   
        // cm.bindProcessToNetwork(network);
       //} else {   
         // 23后这个方法舍弃了  
 
         ConnectivityManager.setProcessDefaultNetwork(network);
       //}
 } catch (IllegalStateException e) {
 Log.e(TAG, "ConnectivityManager.NetworkCallback.onAvailable: ", e);
 }
 }


 // Be sure to override other options in NetworkCallback() too...
 });
}
 /*修改外置摄像头只能通过wifi上网  end 20180619*/

但我们的要求是一个APP有的数据走wifi有的数据走4g,不希望APP和某个network绑定,这样就是要求默认走4g上网,访问内网ip则走wifi.即修改系统让4g的优先级优于wifi,修改route rule,使得访问内网ip时,则走wifi. 

修改系统让4g的优先级优于wifi: 

android5.1是依据网络评分来评定网络的优先级,默认情况下,wifi的评分比4g高。可以修改 

修改网络连接优先级为

Ethernet > Mobile > Wifi


修改


[java]  view plain  copy




    1. diff --git a/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DataConnection.java  
    2. old mode 100644  
    3. new mode 100755  
    4. index 09b3c9b..00fba2a  
    5. --- a/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DataConnection.java  
    6. +++ b/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DataConnection.java  
    7. @@ -1734,7 +1734,7 @@ public final class DataConnection extends StateMachine {  
    8.              misc.subscriberId = mPhone.getSubscriberId();  
    9. new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),  
    10. "DcNetworkAgent", mNetworkInfo, makeNetworkCapabilities(), mLinkProperties,  
    11. -                    50, misc);  
    12. +                    100, misc);  
    13.          }  
    14.    
    15. @Override  
    16. diff --git a/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DctController.java b/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DctController.java  
    17. old mode 100644  
    18. new mode 100755  
    19. index 4fce2ec..fdb59b1  
    20. --- a/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DctController.java  
    21. +++ b/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DctController.java  
    22. @@ -152,7 +152,7 @@ public class DctController extends Handler {  
    23. new TelephonyNetworkFactory(this.getLooper(),  
    24. "TelephonyNetworkFactory", phoneBase,  
    25.                  mNetworkFilter[index]);  
    26. -        mNetworkFactory[index].setScoreFilter(50);  
    27. +        mNetworkFactory[index].setScoreFilter(100);  
    28. new Messenger(mNetworkFactory[index]);  
    29. "Telephony");  
    30.      }



    说明

    网络优先级采用新的score机制.

    以上改法, 将移动网络的score从50 加到 100.

    从当前代码中看,

    Ethernet (150), Wifi(60)
    frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java(Wifi)

    [java]  view plain  copy



    1. mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext,  
    2. "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter,  
    3. 60);


    [java]  view plain  copy



    1. mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext,  
    2.         NETWORKTYPE, mNetworkCapabilitiesFilter);  
    3. mNetworkFactory.setScoreFilter(60);


    frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java(Ethernet)


    [java]  view plain  copy



    1. private static final int NETWORK_SCORE = 150;   
    2. // Create our NetworkAgent.  
    3. new NetworkAgent(mFactory.getLooper(), mContext,  
    4.                             NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,  
    5.                             NETWORK_SCORE) {


    把4g网络评分强制改为100,这样可以确保总是大于wifi网络的评分。 
    更新系统,ping www.baidu.com可以ping通,说明此时系统优先走4g网络(wifi AP与外网断开)。 ping 192.168.10.1 不通。

    修改route rule:

    查看默认route rule: 

    ip rule 
    0: from all lookup local 
    10000: from all fwmark 0xc0000/0xd0000 lookup 99 
    13000: from all fwmark 0x10063/0x1ffff lookup 97 
    13000: from all fwmark 0x10064/0x1ffff lookup 1022 
    13000: from all fwmark 0x10065/0x1ffff lookup 1005 
    14000: from all oif wlan0 lookup 1022 
    14000: from all oif rmnet_data0 lookup 1005 
    15000: from all fwmark 0x0/0x10000 lookup 99 
    16000: from all fwmark 0x0/0x10000 lookup 98 
    17000: from all fwmark 0x0/0x10000 lookup 97 
    19000: from all fwmark 0x64/0x1ffff lookup 1022 
    19000: from all fwmark 0x65/0x1ffff lookup 1005 
    22000: from all fwmark 0x0/0xffff lookup 1005 
    23000: from all fwmark 0x0/0xffff uidrange 0-0 lookup main 
    32000: from all unreachable

    尝试添加一条route rule: 

    ip rule add to 192.168.10.0/24 table wlan0 pref 100 
    修改后route rule: 
    0: from all lookup local 
    100: from all to 192.168.10.0/24 lookup 1022 
    10000: from all fwmark 0xc0000/0xd0000 lookup 99 
    13000: from all fwmark 0x10063/0x1ffff lookup 97 
    13000: from all fwmark 0x10064/0x1ffff lookup 1022 
    13000: from all fwmark 0x10065/0x1ffff lookup 1005 
    14000: from all oif wlan0 lookup 1022 
    14000: from all oif rmnet_data0 lookup 1005 
    15000: from all fwmark 0x0/0x10000 lookup 99 
    16000: from all fwmark 0x0/0x10000 lookup 98 
    17000: from all fwmark 0x0/0x10000 lookup 97 
    19000: from all fwmark 0x64/0x1ffff lookup 1022 
    19000: from all fwmark 0x65/0x1ffff lookup 1005 
    22000: from all fwmark 0x0/0xffff lookup 1005 
    23000: from all fwmark 0x0/0xffff uidrange 0-0 lookup main 
    32000: from all unreachable这样就可以直接ping 通192.168.10.1了。


    APP程序没有修改route rule的权限,我们想让系统在wifi连接AP后自动添加需要的一条route rule. 
    可以修改netd (system/netd/server/),netd有权限修改route rule.