Android 7系统网络(四)Native层(下)—netd Controller详解
2026/7/11 3:57:12 网站建设 项目流程

系列目录:第一篇:全景图与调用链路概览 | 第二篇:内核层—netfilter/iptables与路由策略 | 第三篇:Native层(上)—netd守护进程与CommandListener |第四篇:Native层(下)—netd Controller详解| 第五篇:Framework层(上)—ConnectivityService核心机制 | 第六篇:Framework层(下)—NMS/NPMS/NSS三大服务 | 第七篇:连接建立—WiFi/移动数据/以太网完整流程 | 第八篇:应用API层—ConnectivityManager使用与实战调试


一、Controller 层概述

如果说 CommandListener 是 netd 的"耳朵",Controller 层就是 netd 的"手"——所有实际的网络操作都在 Controller 中执行。

netd 内部有八类主要的 Controller:

CommandListener(命令接收) │ ├── NetworkController ← 网络接口管理 ├── RouteController ← 路由策略管理 ├── FirewallController ← 防火墙(UID过滤) ├── BandwidthController ← 带宽控制(流量限制) ├── TetherController ← 网络共享 ├── SoftapController ← WiFi热点管理 ├── IdletimerController ← 接口空闲检测 └── ResolverController ← DNS解析器管理

每个 Controller 对应一类网络操作,由 CommandListener 的对应 Cmd 类转发调用。


二、NetworkController — 网络接口管理

源码路径system/netd/server/NetworkController.cpp

NetworkController管理网络接口的生命周期:创建/销毁物理网络和虚拟网络、将接口绑定到指定网络、设置默认网络、管理网络权限。

核心方法:

intcreatePhysicalNetwork(unsignednetId,Permission permission);intcreateVirtualNetwork(unsignednetId,boolhasDns,boolsecure);intdestroyNetwork(unsignednetId);intaddInterfaceToNetwork(unsignednetId,constchar*interface);intremoveInterfaceFromNetwork(unsignednetId,constchar*interface);intsetDefaultNetwork(unsignednetId);

关键设计:每个网络由netId标识,接口通过addInterfaceToNetwork绑定到网络,而非直接操作接口属性。IP 地址配置由上层通过netdinterface命令间接完成。

以 WiFi 连接获取 IP 为例的调用过程:

NetworkController.createPhysicalNetwork(100, PERMISSION_SYSTEM) → 创建 netId=100 的物理网络 NetworkController.addInterfaceToNetwork(100, "wlan0") → 将 wlan0 接口绑定到 netId=100 NetworkController.setDefaultNetwork(100) → 设置 netId=100 为默认网络,后续路由走此网络

关键netId范围是 100-65535(与ConnectivityService保持同步),物理网络和虚拟网络使用不同的创建方法。


三、RouteController — 路由策略管理

源码路径system/netd/server/RouteController.cpp

RouteController是 Android 多网络并存的关键。它为每个网络(netId)创建独立的路由表,配置 fwmark 策略路由规则,管理 VPN 路由优先级,保护直连路由避免被默认路由覆盖。

核心方法:

staticintaddInterfaceToPhysicalNetwork(unsignednetId,constchar*interface,Permission permission);staticintremoveInterfaceFromPhysicalNetwork(unsignednetId,constchar*interface,Permission permission);staticintaddInterfaceToVirtualNetwork(unsignednetId,constchar*interface,boolsecure,constUidRanges&uidRanges);staticintremoveInterfaceFromVirtualNetwork(unsignednetId,constchar*interface,boolsecure,constUidRanges&uidRanges);staticintaddRoute(constchar*interface,constchar*destination,constchar*nexthop,TableType tableType);staticintremoveRoute(constchar*interface,constchar*destination,constchar*nexthop,TableType tableType);

关键设计RouteController的所有方法都是static,不维护实例状态,直接操作内核路由表和策略规则。

fwmark 优先级表定义:

constuint32_tRULE_PRIORITY_VPN_OVERRIDE_SYSTEM=10000;constuint32_tRULE_PRIORITY_VPN_OVERRIDE_OIF=10500;constuint32_tRULE_PRIORITY_VPN_OUTPUT_TO_LOCAL=11000;constuint32_tRULE_PRIORITY_SECURE_VPN=12000;constuint32_tRULE_PRIORITY_PROHIBIT_NON_VPN=12500;constuint32_tRULE_PRIORITY_EXPLICIT_NETWORK=13000;constuint32_tRULE_PRIORITY_OUTPUT_INTERFACE=14000;constuint32_tRULE_PRIORITY_LEGACY_SYSTEM=15000;constuint32_tRULE_PRIORITY_LEGACY_NETWORK=16000;constuint32_tRULE_PRIORITY_LOCAL_NETWORK=17000;constuint32_tRULE_PRIORITY_TETHERING=18000;constuint32_tRULE_PRIORITY_IMPLICIT_NETWORK=19000;constuint32_tRULE_PRIORITY_BYPASSABLE_VPN=20000;constuint32_tRULE_PRIORITY_VPN_FALLTHROUGH=21000;constuint32_tRULE_PRIORITY_DEFAULT_NETWORK=22000;constuint32_tRULE_PRIORITY_DIRECTLY_CONNECTED=23000;constuint32_tRULE_PRIORITY_UNREACHABLE=32000;

关键设计:优先级数值越小越优先,从 VPN(10000)到不可达(32000)共 16 级,覆盖了 VPN 覆盖、显式网络、传统网络、网络共享、直连路由等全部场景。

优先级常量数值用途
VPN_OVERRIDE_SYSTEM10000VPN 覆盖系统网络
VPN_OVERRIDE_OIF10500VPN 覆盖出口接口
VPN_OUTPUT_TO_LOCAL11000VPN 发往本地的流量
SECURE_VPN12000安全 VPN(不允许绕过)
PROHIBIT_NON_VPN12500禁止非 VPN 流量
EXPLICIT_NETWORK13000应用显式绑定的网络
DEFAULT_NETWORK22000默认网络(较低优先级)

关键:应用通过bindProcessToNetwork()显式绑定的网络走EXPLICIT_NETWORK(13000),未绑定的 Socket 走DEFAULT_NETWORK(22000),确保显式绑定优先于默认路由。

典型设备上的 ip rule 输出:

iprule show# 0: from all lookup local# 10000: from all fwmark 0x3e8/0xc0000 lookup 1000 ← VPN 优先# 13000: from all fwmark 0x64/0x1ffff lookup 100 ← netId=100 (WiFi)# 13000: from all fwmark 0x65/0x1ffff lookup 101 ← netId=101 (移动数据)# 22000: from all fwmark 0x0/0x0 lookup 99 ← 默认

关键:每个网络拥有独立的fwmark标记和路由表,内核根据fwmark值选择对应的路由表进行查找,实现多网络流量隔离。


四、FirewallController — 防火墙

源码路径system/netd/server/FirewallController.cpp

FirewallController基于 UID 控制应用的网络访问权限,通过 iptables 的-m owner --uid-owner匹配实现。

防火墙链定义:

constchar*LOCAL_INPUT="fw_INPUT";constchar*LOCAL_OUTPUT="fw_OUTPUT";constchar*LOCAL_FORWARD="fw_FORWARD";constchar*LOCAL_DOZABLE="fw_dozable";constchar*LOCAL_STANDBY="fw_standby";constchar*LOCAL_POWERSAVE="fw_powersave";

关键设计fw_INPUTfw_OUTPUTfw_FORWARD是框架链,fw_dozablefw_standbyfw_powersave是子链,子链通过setupIptablesHooks()按需挂载到框架链上。

触发条件限制规则
fw_standby待机状态限制后台应用的网络
fw_powersave省电模式限制所有应用使用移动数据
fw_dozableDoze 深度睡眠严格限制网络访问

核心方法:

intsetFirewallUidRule(intchain,intuid,intrule);

关键:防火墙支持 BLACKLIST 和 WHITELIST 两种模式,默认为黑名单模式。

对应的 iptables 操作:

# 禁止 UID 10086 使用 WiFiiptables-Ifw_standby-owlan0-mowner --uid-owner10086-jREJECT# 省电模式下禁止 UID 10086 使用移动数据iptables-Ifw_powersave-ormnet_data0-mowner --uid-owner10086-jREJECT

关键fw_dozable链同时作用于 INPUT 和 OUTPUT,同时拦截接收和发送的 IPv6 邻居发现报文也会被放行,避免 Doze 模式导致 IPv6 完全不可用。

省电模式切换时的规则变化流程:

用户关闭屏幕 → Doze 模式 ↓ NetworkPolicyManagerService 判断是否进入省电 ↓ NetworkManagementService.setFirewallUidRule(FIREWALL_CHAIN_DOZABLE, uid, DENY) ↓ 通过 NativeDaemonConnector 向 netd 发送命令: ↓ "firewall set_uid_rule dozable <uid> deny" ↓ FirewallController 执行 iptables -I fw_dozable -m owner --uid-owner <uid> -j REJECT ↓ 该 UID 的应用发出的所有网络请求被拒绝

关键FIREWALL_CHAIN_DOZABLE是 Java 层的枚举常量,对应 netd 侧的fw_dozable链,两层命名有差异但通过getFirewallChainName()映射。


五、BandwidthController — 带宽控制

源码路径system/netd/server/BandwidthController.cpp

BandwidthController依赖内核的xt_qtaguid模块,控制网络的带宽使用限制:设置接口的配额限制(每天/每月流量上限)、设置全局警告阈值、限制特定 UID 的带宽。

xt_qtaguid的工作原理:

应用 (UID=10086) Socket.send() ↓ 内核 xt_qtaguid 模块 ├── 检查接口配额 → 未超 → 放行 │ → 已超 → DROP └── 更新统计计数 ↓ 统计数据写入 /proc/net/xt_qtaguid/stats ↓ NetworkStatsService 定期读取统计文件

关键xt_qtaguid在内核协议栈中拦截每个数据包,统计和限额检查都在内核态完成,不存在用户态代理的性能开销。

核心命令:

# 启用带宽控制bandwidthenable# 设置接口配额(字节)bandwidth setiquota rmnet_data01073741824# 1GB# 设置全局警告阈值bandwidth setglobalalert943718400# 900MB 警告# 移除接口配额bandwidth removeiquota rmnet_data0# 设置接口告警(到达指定流量后告警)bandwidth setinterfacealert rmnet_data0524288000# 500MB 告警

关键:配额和告警是独立的——配额超限会直接丢弃数据包,告警只产生通知事件,两者可以组合使用。


六、TetherController — 网络共享

源码路径system/netd/server/TetherController.cpp

TetherController实现 USB 和 WiFi 网络共享功能,依赖三种技术:

技术作用
IP 转发允许数据包从内网转发到外网
iptables NAT (MASQUERADE)将内网 IP 替换为外网接口 IP
DHCP 服务器(dnsmasq)为连接的设备分配 IP 和 DNS

启动网络共享的完整流程:

用户开启 WiFi 热点 ↓ ConnectivityManager.startTethering() ↓ NetworkManagementService.tetherInterface("wlan0") ↓ 向 netd 发送:tether interface add wlan0 ↓ TetherController::tetherInterface("wlan0") ├── 1. 启用 IP 转发:echo 1 > /proc/sys/net/ipv4/ip_forward ├── 2. 添加 NAT 规则:iptables -t nat -A POSTROUTING -o rmnet_data0 -j MASQUERADE ├── 3. 添加 FORWARD 规则 │ iptables -A FORWARD -i wlan0 -o rmnet_data0 -j ACCEPT │ iptables -A FORWARD -i rmnet_data0 -o wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT ├── 4. 配置 wlan0 的 IP:ifconfig wlan0 192.168.43.1 netmask 255.255.255.0 up └── 5. 启动 dnsmasq DHCP 服务器

关键:FORWARD 链的ESTABLISHED,RELATED规则只放行已建立连接的回包,确保外网设备无法主动向内网发起连接。

TetherController支持同时共享多个下游接口,通过mInterfaces列表管理。


七、SoftapController — WiFi 热点

源码路径system/netd/server/SoftapController.cpp

SoftapController管理 WiFi 热点的软件配置。它不直接操作 WiFi 硬件(由hostapd负责),而是管理 AP 接口的创建与删除、SSID/密码/加密方式的配置、信道选择等。

TetherController的协作关系:

SoftapController::startSoftap() ↓ 启动 hostapd,创建 AP Interface ↓ NetworkManagementService ↓ setIpForwardingEnabled(true) ↓ startTethering(["wlan0"]) → 调用 TetherController ↓ TetherController 配置 NAT + FORWARD 规则,启动 dnsmasq DHCP ↓ 网络共享可用

关键SoftapController负责 WiFi 硬件的 AP 模式配置,TetherController负责 IP 层的 NAT 和 DHCP,两者职责分离,通过NetworkManagementService协调。


八、IdletimerController — 空闲检测

源码路径system/netd/server/IdletimerController.cpp

IdletimerController监控网络接口的空闲状态。当接口在指定时间内没有流量时,触发告警。基于内核的xt_IDLETIMER模块实现。

典型使用场景是运营商要求数据连接在空闲一段时间后断开:

IdletimerController 监控 rmnet_data0,timeout = 600 秒 ├── 有流量 → 重置计时器 └── 10分钟无流量 → 触发告警 ↓ NetworkManagementService 收到空闲通知 ↓ ConnectivityService 断开移动数据连接

关键xt_IDLETIMER通过/sys/class/net/<iface>/idletimer接口与用户态通信,计时器在内核中维护,没有用户态定时器的精度问题。



九、ndc 命令实战

ndc(Native Daemon Connector)是一个命令行工具,可以直接向netd发送命令:

# 列出所有网络接口ndc interface list# 查看防火墙状态ndc firewall is_enabled# 添加带宽控制接口ndc bandwidth setiquota rmnet_data01073741824# 查看 tether 状态ndc tether status# 添加路由ndc network routeadd100wlan00.0.0.0/0192.168.1.1

关键ndc的命令格式与NativeDaemonConnector发送的协议完全一致,输出直接反映netd的内部状态,是调试网络问题的首选工具。


十、本篇总结

八大 Controller 各司其职,共同构成了netd的执行层:

Controller操作内核对象上层调用方
NetworkController网络接口(ioctl + netlink)ConnectivityService
RouteController路由表 + ip ruleConnectivityService
FirewallControlleriptables (filter表)NetworkPolicyManagerService
BandwidthControllerxt_qtaguidNetworkPolicyManagerService
TetherControlleriptables (nat表) + dnsmasqConnectivityService
SoftapControllerhostapd 配置WifiStateMachine
IdletimerControllerxt_IDLETIMERConnectivityService
ResolverControllerDNS 服务器配置ConnectivityService

每个 Controller 都是对特定内核机制的一层封装。下一篇将上升到 Framework 层,深入ConnectivityService的网络评分与切换机制。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询