1 基本概念
1.1 Android任何网络类型
1)与netd打交道通过INetworkManagementService 
2)与ConnectivityService 打交道通过NetworkAgent

1.2 检查是否有网络连接
Java网络库API路径:Android_project/libcore
Android判断网络是否连接:
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public static boolean isNetworkConnected(
    Context context) {
    if (context != null) {
        ConnectivityManager connectivityManager =
            (ConnectivityManager)context
            .getSystemService(
            Context.CONNECTIVITY_SERVICE);
        // Ethernet, WiFi, Mobile
        NetworkInfo networkInfo =
        connectivityManager.getActiveNetworkInfo();
        if (networkInfo != null) {
            return networkInfo.isAvailable();
        }
    }
    return false;
}

使用命令dumpsys connectivity查看激活的网络和该网络的得分。

1.3 实施方法
连接高优先级的网络,低优先级的不断开。
frameworks/base/services/core/java/com/android/server/ConnectivityService.java
private void
teardownUnneededNetwork(NetworkAgentInfo nai) {
    if (SystemProperties.getBoolean(
        "ro.net.coexist", false)) {
        return;
    }
    [...]
}

2 路由添加语法
ip route add {NETWORK/MASK} via {GATEWAYIP}
ip route add {NETWORK/MASK} dev {DEVICE}
ip route add default {NETWORK/MASK} dev {DEVICE}
ip route add default {NETWORK/MASK} via {GATEWAYIP}

ip route add default via 192.168.0.1 dev eth0 \
table 1

# ip rule add from all lookup main pref 9999
# 上一条命令等价于在netd中添加modifyIpRule(RTM_NEWRULE, 9999, 254, 0, 0);
ip rule add from 192.168.0.0/24 table 1
ip rule add to 192.168.0.0/24 table 1
table 1中包含了eth0默认网关,而table main中包含了正常的eth0路由。

3 Android netId
3.1 获取网络接口的netId
netd中将接口名(wlan0、eth0等)转化为netId的函数:
server/NetworkController.cpp
NetworkController::getNetworkForInterface(
    const char* interface)

3.2 代码示例
server/CommandListener.cpp
函数CommandListener::NetworkCommand::runCommand()的最后添加如下的代码:
//       0              1              2
// network query_netid if_name
if (!strcmp(argv[1], "query_netid")) {
    if (argc < 3) {
        return syntaxError(client,
            "Missing argument");
    }
    int _netId =
        gCtls->netCtrl.getNetworkForInterface(
            argv[2]);
    char msg[16] = {0};
    int retval = snprintf(msg, 15, "%d", _netId);
    if (retval > 0) {
        client->sendMsg(
            ResponseCode::CommandOkay,
            msg, false);
        return 0;
    } else {
        return operationError(client,
            "Can not get netId", retval);
    }
}
用法:ndc network query_netid wlan0

4 Android UID
4.1 UID查找方法
Android中,使用iptables绑定一个APP到特定的路由时,需要用到UID。
ps -A后每一行的第一个字符串表示UID,查看该UID对应的数值,使用id <parameter>
例如:
id u0_a50

其中u0_a50的含义:
u0:默认的手机第一个用户
a:代表app
50:代表着第50个应用

转换公式:
u0_a50 = “u0_” + “a” + (uid(这里是10050) – FIRST_APPLICATION_UID(固定值10000))

4.2 UID查找脚本示例
#!/vendor/bin/sh

APP_LIST=("com.android.email"
 "com.android.systemui"
 "android.hardware.audio@2.0-service")

SH_PS="/vendor/bin/ps"
SH_GREP="/vendor/bin/grep"
SH_ID="/vendor/bin/id"
SH_TR="/vendor/bin/tr"
SH_ECHO="/vendor/bin/echo"
SH_TEE="/vendor/bin/tee"
SH_USLP="/vendor/bin/usleep"

for app in ${APP_LIST[@]}
do
    count=1
    while [ $count -le 10 ]; do
        line=$($SH_PS -A | $SH_GREP ${app})
        if [ $? -eq 0 ]; then
            $SH_ECHO "got ${app}, count $count" \
                | $SH_TEE /dev/kmsg
            break
        fi

$SH_ECHO "waiting ${app}, count $count" \
                | $SH_TEE /dev/kmsg
        $SH_USLP 500000
        count=$((count + 1))
    done

line=$($SH_PS -A | $SH_GREP ${app})
    if [ $? -eq 0 ]; then
        list=(${line}) # switch str to list
        # len=${#list[@]} # length of list
        # len=$((len - 1))
        uid_str=${list[0]}

line=$($SH_ID $uid_str)
        list=(${line}) # switch str to list
        uid_str=${list[0]}
        # uid=10017(u0_a17) -> uid=10017
        uid_str=${uid_str%\(*}

uid=$($SH_ECHO $uid_str | \
            $SH_TR -cd "[0-9]")
        # Now got the process UID
        $SH_ECHO $uid | $SH_TEE /dev/kmsg
    fi
done

5 绑定某个应用到指定的网络
5.1 Linux netfilter hook
Linux内核网络代码被netfilter cut off的函数都分为了两个阶段:XXX以及XXX_finish。
struct nf_hook_ops
nf_register_net_hook()
nf_unregister_net_hook()

kernel IPv4 print: %pI4
user IPv4 print: inet_ntoa
meta|match1|match2|...|target

5.1.1 match
iptables -m xxx: xxx = kernel struct xt_match, libipt_xxx.so
net/netfilter/xt_owner.c
external/iptables/extensions/libxt_owner.c

5.1.2 target
iptables -j xxx: xxx = kernel struct xt_target, libipt_xxx.so

xt_register_target()
xt_unregister_target()

5.2 Android API
bindProcessToNetwork()
netd中hook了socket()、connect()和accept()等API。
bionic/libc/bionic/socket.cpp
bionic/libc/bionic/connect.cpp
system/netd/client/NetdClient.cpp
FwmarkClient::shouldSetFwmark(int family)

5.3 命令行方式
1)添加main rule
ip rule add from all lookup main pref 9999

2)为eth0接口添加VLAN ID 5
ip link add link eth0 name eth0.5 type vlan id 5
ip -d link show eth0.5

3)设置VLAN QOS
i=0
while [ $i -le 7 ]; do
    ip link set dev eth0.5 type vlan \
        egress-qos-map $i:0
    # ip link set eth0.5 type vlan egress $i:0
    i=$((i + 1))
done
其中$i表示skb_priority,0表示vlan_qos,vlan_qos对应到VLAN以太网帧中的3bit PCP。因为PCP的值越大优先级越高,由于AVB PCP的值为2(Class B,2B,250us)和3(Class A,3A,125us),所以将普通应用程序的PCP值都设置为0后,就低于AVB流的优先级了。

4)分配IP并启动
ip addr add 192.168.5.200/24 brd 192.168.5.255 \
dev eth0.5
ip link set dev eth0.5 up
或者
ifconfig eth0.5 192.168.5.200/24 up

5)设置iptables fwmark
ip rule add fwmark 0x66 priority 9998 table 200
ip route add 192.168.5.0/24 via 192.168.5.1 \
dev eth0.5 table 200
ip route flush cache

# -j means jump, u0_a50 = 10050
# net/netfilter/xt_owner.c
# external/iptables/extensions/libxt_owner.c
iptables -t mangle -A OUTPUT -m owner \
--uid-owner u0_a50 -j MARK --set-mark 0x66
echo 0x66 > \
/proc/sys/net/ipv4/conf/eth0.5/rp_filter

# delete this fwmark
# iptables -t mangle -D OUTPUT -m owner \
--uid-owner u0_a50 -j MARK --set-mark 0x66
# echo 0 > \
/proc/sys/net/ipv4/conf/eth0.5/rp_filter

# merge ip rule and iptables to one
# ip rule add uidrange 10050-10050 priority 9998 table 200
# ip rule del uidrange 10050-10050 priority 9998 table 200

6)查看是否生效
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NETFILTER_XT_TARGET_LOG=m

iptables -A PREROUTING -t raw -i eth0 \
-j TRACE
iptables -A OUTPUT -t raw -o eth0 \
-j TRACE
echo "nf_log_ipv4" > \
/proc/sys/net/netfilter/nf_log/2

dmesg | grep TRACE

6 Abbreviations
fwmark:firewall mark
ojluni:Android libcore中的模块,包含OpenJDK、Language、Util、Net、IO
svc:Supervisor Call

Android多网络并存相关推荐

  1. Android中网络使用

    Android中判断网络连接是否可用 一.判断网络连接是否可用 public static boolean isNetworkAvailable(Context context) { Connecti ...

  2. android 代码获取图片信息吗,Android 通过网络获取图片的代码

    Android 通过网络获取图片的代码 主activity package com.netimg; import android.app.Activity; import android.graphi ...

  3. android 检查网络连接状态实现步骤

     android 如何检查网络连接状态,是android开发中一个常见的问题,本文将介绍如何实现,需要的朋友可以参考下 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限 ...

  4. android系统电量优化,基于Android系统网络耗电量优化方法的.pdf

    基于Android系统网络耗电量优化方法的 2012年第10期,第 45卷 通 信 技 术 Vol.45,No.10,2012 总第250期 Communications Technology No. ...

  5. Android检查网络状态步骤

    android 如何检查网络连接状态,是android开发中一个常见的问题. 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限: <span style=" ...

  6. android 判断网络是否可用

    今天也是没有什么好写的,但是自己的强迫症似乎又犯了,觉得每天写博客的习惯不能改,所以在网上搜索了资料,写了这些内容. 一.检查网络是否可用,并且弹出提示框,用户可以去设置网络. package com ...

  7. Android 监控网络状态

    Html代码 public static boolean isNetworkAvailable(Context context) { ConnectivityManager connectivity  ...

  8. Android技能树 — 网络小结(6)之 OkHttp超超超超超超超详细解析

    前言: 本文也做了一次标题党,哈哈,其实写的还是很水,各位原谅我O(∩_∩)O. 介于自己的网络方面知识烂的一塌糊涂,所以准备写相关网络的文章,但是考虑全部写在一篇太长了,所以分开写,希望大家能仔细看 ...

  9. Android检测网络是否正常代码!

    在Android开发中,如果该应用程序需要连接网络请求,那么最好我们先做一个检测网络是否在线的判断,否则程序容易出现卡死或FC等Bug,应该判断如果手机离线则弹出提示让用户检查网络,如果正常则继续执行 ...

最新文章

  1. python opencv卡尺测量边缘距离
  2. 2011年计算机等级考试二级java笔试练习题(10)_2010年3月计算机等级考试二级Java笔试题及答案...
  3. VTK:模型之Delaunay3DDemo
  4. [渝粤教育] 中国地质大学 金融保险业会计 复习题 (2)
  5. python标签打印工具_NiceLabel Designer 2017条码标签打印软件
  6. 关于线段树套伸展树被卡常
  7. ROS2 Galactic Depth to World coordinate RGBD相机的深度数据转换到世界坐标系
  8. Sql Server 分区之后增加新的分区
  9. 大厂面经----接近30场面试分享
  10. 全面解析云智慧数据中心统一运管解决方案
  11. 安装VMware出现无法访问你试图使用的功能所在的网络位置
  12. c语言常量10进制,C语言常量
  13. 一位过来人:也谈谈体制内 • 体制外
  14. 银河麒麟最新V10系统下载链接
  15. ORA-600 Lookup Error Categories
  16. 网易裁员,让保安把身患绝症的员工赶出公司!前网易员工亲述经历的噩梦!...
  17. android 解压rar5,RAR解压缩软件_Winrar官方版 V5.50.42 安卓去广告版
  18. H5游戏性能测试工具 选择与实践总结
  19. php的sic考试,关于V9项目M2 SIC考试题调查分析
  20. linux内核日志使用syslog,Linux日志系统syslog详解

热门文章

  1. Linux常用基本命令【分类查询版】(超实用不来看看嘛?)
  2. 几个方法,告诉你PDF怎么转换成Word免费!
  3. RSA+AES数字信封加解密设计
  4. Centos 7安装UHD教程
  5. 将CAD模型通过SolidWorks导出机器人URDF文件(基于innfos六轴机械臂)
  6. L2-030 冰岛人PTA
  7. mongodb文档太大_了解MongoDB BSON文档大小限制
  8. python黑客培训教程
  9. 每日学术速递3.17
  10. ant design table 表格空白