Android多网络并存
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多网络并存相关推荐
- Android中网络使用
Android中判断网络连接是否可用 一.判断网络连接是否可用 public static boolean isNetworkAvailable(Context context) { Connecti ...
- android 代码获取图片信息吗,Android 通过网络获取图片的代码
Android 通过网络获取图片的代码 主activity package com.netimg; import android.app.Activity; import android.graphi ...
- android 检查网络连接状态实现步骤
android 如何检查网络连接状态,是android开发中一个常见的问题,本文将介绍如何实现,需要的朋友可以参考下 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限 ...
- android系统电量优化,基于Android系统网络耗电量优化方法的.pdf
基于Android系统网络耗电量优化方法的 2012年第10期,第 45卷 通 信 技 术 Vol.45,No.10,2012 总第250期 Communications Technology No. ...
- Android检查网络状态步骤
android 如何检查网络连接状态,是android开发中一个常见的问题. 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限: <span style=" ...
- android 判断网络是否可用
今天也是没有什么好写的,但是自己的强迫症似乎又犯了,觉得每天写博客的习惯不能改,所以在网上搜索了资料,写了这些内容. 一.检查网络是否可用,并且弹出提示框,用户可以去设置网络. package com ...
- Android 监控网络状态
Html代码 public static boolean isNetworkAvailable(Context context) { ConnectivityManager connectivity ...
- Android技能树 — 网络小结(6)之 OkHttp超超超超超超超详细解析
前言: 本文也做了一次标题党,哈哈,其实写的还是很水,各位原谅我O(∩_∩)O. 介于自己的网络方面知识烂的一塌糊涂,所以准备写相关网络的文章,但是考虑全部写在一篇太长了,所以分开写,希望大家能仔细看 ...
- Android检测网络是否正常代码!
在Android开发中,如果该应用程序需要连接网络请求,那么最好我们先做一个检测网络是否在线的判断,否则程序容易出现卡死或FC等Bug,应该判断如果手机离线则弹出提示让用户检查网络,如果正常则继续执行 ...
最新文章
- python opencv卡尺测量边缘距离
- 2011年计算机等级考试二级java笔试练习题(10)_2010年3月计算机等级考试二级Java笔试题及答案...
- VTK:模型之Delaunay3DDemo
- [渝粤教育] 中国地质大学 金融保险业会计 复习题 (2)
- python标签打印工具_NiceLabel Designer 2017条码标签打印软件
- 关于线段树套伸展树被卡常
- ROS2 Galactic Depth to World coordinate RGBD相机的深度数据转换到世界坐标系
- Sql Server 分区之后增加新的分区
- 大厂面经----接近30场面试分享
- 全面解析云智慧数据中心统一运管解决方案
- 安装VMware出现无法访问你试图使用的功能所在的网络位置
- c语言常量10进制,C语言常量
- 一位过来人:也谈谈体制内 • 体制外
- 银河麒麟最新V10系统下载链接
- ORA-600 Lookup Error Categories
- 网易裁员,让保安把身患绝症的员工赶出公司!前网易员工亲述经历的噩梦!...
- android 解压rar5,RAR解压缩软件_Winrar官方版 V5.50.42 安卓去广告版
- H5游戏性能测试工具选择与实践总结
- php的sic考试,关于V9项目M2 SIC考试题调查分析
- linux内核日志使用syslog,Linux日志系统syslog详解