文章目录
- [Android10 添加以太网网络共享功能](#Android10 添加以太网网络共享功能)
-
- 一、前言
- 二、需求分析
- 三、系统架构与原理
-
- [3.1 整体架构](#3.1 整体架构)
- [3.2 代码执行流程](#3.2 代码执行流程)
- [3.3 IP 网段分配](#3.3 IP 网段分配)
- 四、修改文件概览
- 五、详细实现
-
- [5.1 定义 Tethering 类型](#5.1 定义 Tethering 类型)
- [5.2 增加以太网状态广播](#5.2 增加以太网状态广播)
- [5.3 Tethering 核心逻辑改造](#5.3 Tethering 核心逻辑改造)
-
- [5.3.1 接口类型识别](#5.3.1 接口类型识别)
- [5.3.2 自动开启以太网共享](#5.3.2 自动开启以太网共享)
- [5.3.3 共享开关实现](#5.3.3 共享开关实现)
- [5.3.4 状态广播与清理](#5.3.4 状态广播与清理)
- [5.4 配置识别与 IP 分配](#5.4 配置识别与 IP 分配)
-
- [5.4.1 接口识别规则](#5.4.1 接口识别规则)
- [5.4.2 网关 IP 配置](#5.4.2 网关 IP 配置)
- [5.5 阻止正常网络代理流程](#5.5 阻止正常网络代理流程)
- 六、关键逻辑说明
- 七、总结
Android10 添加以太网网络共享功能
摘要:本文记录在 Android10 AOSP 源码中新增以太网网络共享(Ethernet Tethering)的完整修改过程。通过扩展系统 Tethering 框架,使设备可通过
eth0接口为下游设备提供网络共享服务,适用于工业网关、有线热点等场景。
一、前言
Android 原生系统支持 WiFi、USB、蓝牙三种网络共享方式,但在部分行业设备(如工控平板、车载网关)中,存在通过有线以太网口对外共享网络的需求。Android10 的 Tethering 框架具备良好的扩展性,本文介绍如何在 AOSP 源码中新增 Ethernet Tethering 支持,实现插入网线后自动开启以太网共享。
二、需求分析
核心需求可拆解为以下几点:
- 新增 Tethering 类型 :在系统层定义
TETHERING_ETHERNET,让框架识别以太网共享。 - 接口状态监听 :监听
eth0插拔事件,网线接入后自动触发共享逻辑。 - 状态广播:向上层应用提供以太网连接状态广播,便于 UI 展示。
- IP 地址分配 :为
eth0分配固定的网关地址,并启动 DHCP 服务为下游设备分配 IP。 - 避免冲突 :阻止
eth0走正常的以太网网络连接流程,防止与 Tethering 逻辑冲突。
最终效果:
通过网线连接PC和设备
Android设备IP:

PC 设备IP

三、系统架构与原理
3.1 整体架构
在 Android 网络体系中,Tethering 模块位于 ConnectivityService 之下、Netd 之上,负责管理所有下游共享接口。本次修改的整体架构如下:
┌─────────────────────────────────────────┐
│ 应用层 (SystemUI/APK) │
│ 接收 ETHERNET_STATE 广播展示状态 │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ Framework API 层 │
│ ConnectivityManager / EthernetManager │
│ (新增 TETHERING_ETHERNET 常量与广播) │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ System Server 层 │
│ ┌─────────────────────────────────┐ │
│ │ Tethering.java (状态机核心) │ │
│ │ • 监听 eth0 插拔事件 │ │
│ │ • 自动 enable/disable 共享 │ │
│ │ • 发送状态广播 │ │
│ └─────────────────────────────────┘ │
│ ┌─────────────────────────────────┐ │
│ │ IpServer.java (地址服务) │ │
│ │ • 配置 192.168.48.1/24 │ │
│ │ • 启动 Dnsmasq DHCP 服务 │ │
│ └─────────────────────────────────┘ │
│ ┌─────────────────────────────────┐ │
│ │ EthernetNetworkFactory.java │ │
│ │ • 拦截 eth0 正常上网流程 │ │
│ └─────────────────────────────────┘ │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ Native 层 (Netd) │
│ 接口状态上报 / iptables 规则下发 │
└─────────────────────────────────────────┘
3.2 代码执行流程
当网线插入设备后,整个共享开启的代码执行流程如下:
匹配 eth0
网线插入 eth0
Kernel 触发 netlink 事件
Netd 上报 interfaceLinkStateChanged
Tethering.interfaceStatusChanged
ifaceNameToType
判断接口类型
识别为 TETHERING_ETHERNET
发送 ACTION_ETHERNET_STATE
Sticky 广播
调用 enableTetheringInternal
进入 setEthernetTethering
调用 tetherMatchingInterfaces
IpServer 进入 STATE_TETHERED
配置 192.168.48.1/24
启动 DHCP + DNS 转发
下游设备通过网线获取 IP 上网
3.3 IP 网段分配
为避免与系统已有的 WiFi 热点、Wigig 共享地址冲突,各共享类型使用独立网段:
| 共享类型 | 接口示例 | 网关地址 | 子网掩码 | DHCP 网段 |
|---|---|---|---|---|
| WiFi | wlan0 | 192.168.42.1 | /24 | 192.168.42.0/24 |
| Ethernet | eth0 | 192.168.48.1 | /24 | 192.168.48.0/24 |
| Wigig | wigig0 | 192.168.50.1 | /24 | 192.168.50.0/24 |
四、修改文件概览
| 文件路径 | 修改说明 |
|---|---|
frameworks/base/core/java/android/net/ConnectivityManager.java |
新增 TETHERING_ETHERNET 常量 |
frameworks/base/core/java/android/net/EthernetManager.java |
新增以太网状态广播 Action 与 Extra |
frameworks/base/core/res/AndroidManifest.xml |
注册 protected broadcast |
frameworks/base/services/core/java/com/android/server/connectivity/Tethering.java |
Tethering 核心逻辑,自动开启/关闭以太网共享 |
frameworks/base/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java |
新增 isEthernet() 接口识别 |
frameworks/base/services/net/java/android/net/ip/IpServer.java |
配置以太网网关 IP 及子网掩码 |
frameworks/base/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java |
阻止 eth0 进入正常网络连接流程 |
五、详细实现
5.1 定义 Tethering 类型
首先,在 ConnectivityManager 中新增以太网共享类型常量,值为 4:
java
// frameworks/base/core/java/android/net/ConnectivityManager.java
/**
* Ethernet tethering type.
* @see #startTethering(int, OnStartTetheringCallback, boolean)
* @hide
*/
public static final int TETHERING_ETHERNET = 4;
5.2 增加以太网状态广播
为了让应用层能感知以太网共享的插拔状态,在 EthernetManager 中定义广播 Action 与 Extra:
java
// frameworks/base/core/java/android/net/EthernetManager.java
/**
* Broadcast Action: A sticky broadcast for ethernet state change events when in device mode.
* {@hide}
*/
public static final String ACTION_ETHERNET_STATE =
"android.net.action.ETHERNET_STATE";
/**
* Boolean extra indicating whether ethernet is connected or disconnected.
* {@hide}
*/
public static final String ETHERNET_CONNECTED = "connected";
同时,在 AndroidManifest.xml 中将其注册为受保护广播,避免第三方应用滥用:
xml
<!-- frameworks/base/core/res/AndroidManifest.xml -->
<<protected-broadcast android:name="android.net.action.ETHERNET_STATE" />
5.3 Tethering 核心逻辑改造
Tethering.java 是本次修改的核心文件,主要完成以下工作:
5.3.1 接口类型识别
在 ifaceNameToType() 中增加对 eth0 的识别:
java
// frameworks/base/services/core/java/com/android/server/connectivity/Tethering.java
private int ifaceNameToType(String iface) {
final TetheringConfiguration cfg = mConfig;
if (cfg.isWifi(iface)) {
// ...
return TETHERING_WIGIG;
} else if (cfg.isUsb(iface)) {
return TETHERING_USB;
} else if (cfg.isBluetooth(iface)) {
return TETHERING_BLUETOOTH;
} else if (cfg.isEthernet(iface)) {
return TETHERING_ETHERNET;
}
return TETHERING_INVALID;
}
5.3.2 自动开启以太网共享
在 interfaceStatusChanged() 中监听接口状态变化。当检测到 eth0 链路 Up 时,发送状态广播,并自动调用内部开启逻辑:
java
// frameworks/base/services/core/java/com/android/server/connectivity/Tethering.java
public void interfaceStatusChanged(String iface, boolean up) {
// ... 原有 WiFi/USB/蓝牙逻辑 ...
int interfaceType = ifaceNameToType(iface);
if (interfaceType == TETHERING_ETHERNET) {
// 发送以太网插拔状态广播
final Intent broadcast = new Intent(EthernetManager.ACTION_ETHERNET_STATE);
broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
broadcast.putExtra(EthernetManager.ETHERNET_CONNECTED, up);
mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
// 自动开启以太网共享
enableTetheringInternal(interfaceType, true, null);
}
}
5.3.3 共享开关实现
在 enableTetheringInternal() 中增加 TETHERING_ETHERNET 分支:
java
case TETHERING_ETHERNET:
result = setEthernetTethering(enable);
sendTetherResult(receiver, result);
break;
setEthernetTethering() 的实现如下:
java
// frameworks/base/services/core/java/com/android/server/connectivity/Tethering.java
public int setEthernetTethering(boolean enable) {
synchronized (mPublicSync) {
if (enable) {
final long ident = Binder.clearCallingIdentity();
try {
tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_ETHERNET);
} finally {
Binder.restoreCallingIdentity(ident);
}
} else {
final long ident = Binder.clearCallingIdentity();
try {
tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_ETHERNET);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
return TETHER_ERROR_NO_ERROR;
}
5.3.4 状态广播与清理
在 sendTetherStateChangedBroadcast() 中增加以太网共享状态标记,并在 untetherAll() 中增加停止逻辑:
java
// frameworks/base/services/core/java/com/android/server/connectivity/Tethering.java
public void untetherAll() {
stopTethering(TETHERING_WIFI);
stopTethering(TETHERING_USB);
stopTethering(TETHERING_ETHERNET);
stopTethering(TETHERING_BLUETOOTH);
}
5.4 配置识别与 IP 分配
5.4.1 接口识别规则
在 TetheringConfiguration 中增加以太网接口判断,当前固定匹配 eth0:
java
// frameworks/base/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
public boolean isEthernet(String iface) {
return iface.equals("eth0");
}
5.4.2 网关 IP 配置
在 IpServer 中,为以太网共享接口分配独立的网段,避免与 WiFi 热点冲突:
java
// frameworks/base/services/net/java/android/net/ip/IpServer.java
private static final String ETHERNET_IFACE_ADDR = "192.168.48.1";
private static final int ETHERNET_PREFIX_LENGTH = 24;
在 configureIPv4() 中根据接口类型选择对应地址:
java
if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
ipAsString = WIFI_HOST_IFACE_ADDR;
prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
} else if (mInterfaceType == ConnectivityManager.TETHERING_ETHERNET) {
ipAsString = ETHERNET_IFACE_ADDR;
prefixLen = ETHERNET_PREFIX_LENGTH;
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIGIG) {
// ...
}
5.5 阻止正常网络代理流程
当 eth0 作为共享下游接口时,必须阻止其进入 EthernetNetworkFactory 的正常网络连接流程(如 DHCP 获取、网络评分等),否则会导致 Tethering 与正常网络栈冲突。
在 EthernetNetworkFactory 的 start() 方法中增加路由模式判断:
java
// frameworks/base/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
private void start() {
// 若当前处于以太网路由/共享模式,则不启动正常网络连接
boolean isEthernetRouterMode = true;
// 实际项目中建议通过 Settings.Global 控制:
// Settings.Global.getInt(mContext.getContentResolver(), ETHERNET_ROUTER_MODE_ON, 0) == 1;
if (isEthernetRouterMode) {
return;
}
if (mIpClient != null) {
if (DBG) Log.d(TAG, "IpClient already started");
return;
}
// ... 原有网络连接逻辑
}
六、关键逻辑说明
- 自动触发机制 :系统通过
Netd监听内核网卡事件,Tethering服务收到eth0的interfaceLinkStateChanged回调后,自动完成共享开启,无需用户手动操作。 - StickyBroadcast:使用粘性广播发送以太网状态,确保应用注册接收器后能立即获取当前连接状态。
- 网段隔离 :以太网共享使用
192.168.48.0/24网段,与 WiFi 热点的192.168.42.0/24、Wigig 的192.168.50.0/24相互独立,避免路由冲突。 - 流程拦截 :
EthernetNetworkFactory中的拦截是本次功能生效的关键,若缺少此步骤,eth0会被系统当作普通以太网上行接口进行 DHCP,导致 Tethering 无法正常分配地址。
七、总结
本文通过在 Android10 Tethering 框架中新增 TETHERING_ETHERNET 类型,实现了以太网口的有线网络共享功能。主要改动集中在:
- Framework API 层:新增常量与广播定义;
- SystemServer 层:改造 Tethering 状态机,实现自动识别与开启;
- 网络协议层:配置独立网段与 DHCP 服务;
- 冲突规避层 :拦截
EthernetNetworkFactory的正常连接流程。
该方案已应用于实际项目,可满足工业设备、车载网关等场景下通过有线网口对外提供网络共享的需求。