Android 7系统网络(七)连接建立—WiFi_移动数据_以太网完整流程 系列目录第一篇全景图与调用链路概览 | 第二篇内核层—netfilter/iptables与路由策略 | 第三篇Native层(上)—netd守护进程与CommandListener | 第四篇Native层(下)—netd Controller详解 | 第五篇Framework层(上)—ConnectivityService核心机制 | 第六篇Framework层(下)—NMS/NPMS/NSS三大服务 |第七篇连接建立—WiFi/移动数据/以太网完整流程| 第八篇应用API层—ConnectivityManager使用与实战调试一、为什么要了解连接建立流程前六篇从内核层讲到 Framework 层所有组件最终都是为网络连接服务的。当你遇到以下问题时理解完整连接流程是排查的关键“为什么 WiFi 已关联但无法获取 IP 地址”——DHCP 阶段DhcpClient可能出了问题“为什么移动数据 APN 配置正确但无法激活数据连接”——DcTracker到RIL的链路可能在某一步卡住了“为什么网线插入后设备没有自动切换到以太网”——EthernetNetworkFactory的 uevent 监听可能没有触发统一模式NetworkFactory → NetworkAgentWiFi、移动数据、以太网虽然底层实现完全不同但向 Framework 层上报时遵循完全相同的模式。理解这个模式后三种网络可以一通百通┌─────────────────────────────────────────────────────────────────┐ │ ConnectivityService │ │ 评分、匹配、默认网络 │ └──────┬──────────────────┬──────────────────┬───────────────────┘ │ NetworkAgent │ NetworkAgent │ NetworkAgent │ (score60) │ (score50) │ (score70) ┌──────┴──────┐ ┌────────┴──────┐ ┌───────┴──────────┐ │ WiFi │ │ 移动数据 │ │ 以太网 │ │ Factory │ │ Factory │ │ Factory │ │ Agent │ │ Agent │ │ Agent │ └─────────────┘ └───────────────┘ └──────────────────┘每种网络都经历同一个五步流程1. 触发连接 ↓ 2. 获取 IP 地址DHCP / Modem 分配 / 静态配置 ↓ 3. 构建 LinkPropertiesIP、网关、DNS NetworkCapabilities ↓ 4. 创建 NetworkAgent注册到 ConnectivityService ↓ 5. NetworkMonitor 验证互联网可达性 → 评分竞争 → 成为默认网络关键设计NetworkFactory负责要不要建NetworkAgent负责建好了通知 Framework。两者分离后每种网络只需实现自己的工厂逻辑Framework 层统一用NetworkAgent接口管理。二、WiFi 连接2.1 状态机架构WiFi 连接由WifiStateMachine层级状态机驱动。StateMachine是 Android 的通用状态机框架addState(child, parent)的缩进直接映射了父子关系源码路径frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.javapublicclassWifiStateMachineextendsStateMachineimplementsWifiNative.WifiRssiEventHandler{// ...privateStatemDefaultStatenewDefaultState();privateStatemSupplicantStartedStatenewSupplicantStartedState();protectedWifiStateMachine(...){addState(mDefaultState);addState(mInitialState,mDefaultState);addState(mSupplicantStartingState,mDefaultState);addState(mSupplicantStartedState,mDefaultState);addState(mDriverStartingState,mSupplicantStartedState);addState(mDriverStartedState,mSupplicantStartedState);addState(mScanModeState,mDriverStartedState);addState(mConnectModeState,mDriverStartedState);addState(mL2ConnectedState,mConnectModeState);addState(mObtainingIpState,mL2ConnectedState);addState(mConnectedState,mL2ConnectedState);addState(mDisconnectedState,mConnectModeState);addState(mDriverStoppingState,mSupplicantStartedState);addState(mDriverStoppedState,mSupplicantStartedState);addState(mSupplicantStoppingState,mDefaultState);addState(mSoftApState,mDefaultState);setInitialState(mInitialState);}}关键设计每层缩进代表一级父子关系最深 4 层嵌套——DefaultState→SupplicantStartedState→DriverStartedState→ConnectModeState→L2ConnectedState。状态迁移时子状态未处理的消息会自动冒泡到父状态形成默认行为。连接成功后状态沿这条路径迁移DefaultState └── SupplicantStartedState ← wpa_supplicant 就绪 └── DriverStartedState ← 驱动运行中 └── ConnectModeState ← 尝试连接 └── L2ConnectedState ← 二层关联完成 ├── ObtainingIpState ← DHCP 获取 IP └── ConnectedState ← 完全连接 ✓2.2 连接五阶段从用户点击连接到 WiFi 就绪分五个阶段。下图展示了每个阶段涉及的核心组件┌──────────┐ ┌─────────────┐ ┌──────────┐ ┌──────────────┐ ┌────────────────────┐ │ 阶段一 │→ │ 阶段二 │→ │ 阶段三 │→ │ 阶段四 │→ │ 阶段五 │ │ 扫描 AP │ │ 认证关联 │ │ DHCP 获取 │ │ 注册 │ │ 验证互联网可达性 │ │ │ │ (二层连接) │ │ IP 地址 │ │ NetworkAgent │ │ │ └─────┬─────┘ └──────┬──────┘ └────┬─────┘ └──────┬───────┘ └─────────┬──────────┘ │ │ │ │ │ WifiNative wpa_supplicant DhcpClient WifiNetworkAgent NetworkMonitor │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ SCAN → 四次握手→ DISCOVER→ sendLinkProperties HTTP 204 scan results CONNECTED事件 OFFER→REQUEST sendNetworkCap → VALIDATED →ACK → 评分竞争阶段一扫描 APWifiStateMachine进入DriverStartedState后自动开始扫描。WifiNative.sendCommand(SCAN)通过 wpa_ctrl socket 向wpa_supplicant下发扫描命令驱动执行扫描后返回结果列表WifiMonitor收到SCAN_RESULTS事件通知WifiStateMachine。阶段二认证与关联二层连接WifiConfigManager获取保存的配置SSID、密码→WifiNative.addNetwork(config)获取 networkId →enableNetwork(networkId)触发关联。wpa_supplicant完成 WPA2-PSK 四次握手和 802.11 关联后发送CONNECTED事件WifiMonitor转发给WifiStateMachine状态迁移到L2ConnectedState。阶段三DHCP 获取 IP源码路径frameworks/base/services/net/java/android/net/dhcp/DhcpClient.javaObtainingIpState启动DhcpClient同样继承StateMachine向 DHCP 服务器发起四步交互publicclassDhcpClientextendsStateMachine{// ...publicstaticfinalintCMD_START_DHCPBASE1;// 启动 DHCPprivatestaticfinalintFIRST_TIMEOUT_MS2*1000;// 初始超时 2 秒privatestaticfinalintMAX_TIMEOUT_MS128*1000;// 最大超时 128 秒指数退避// DHCP 四步交互状态机自动流转// 1. sendDiscoverPacket() → 广播 DHCPDISCOVER// 2. 收到 DHCPOFFER → sendRequestPacket() → 广播 DHCPREQUEST// 3. 收到 DHCPACK → 解析 DhcpResultsIP、网关、DNS、租期// 4. 超时重试2s → 4s → 8s → ... → 128s指数退避}DhcpResults包含IP 地址、子网掩码、网关、DNS 服务器、租期。这些数据将填入LinkProperties。阶段四注册 NetworkAgentL2ConnectedState创建WifiNetworkAgentNetworkAgent的子类构造时传入评分 60。进入ConnectedState后更新链路属性publicclassWifiStateMachineextendsStateMachineimplementsWifiNative.WifiRssiEventHandler{privateWifiNetworkAgentmNetworkAgent;privateLinkPropertiesmLinkProperties;// L2ConnectedState.enter() — 创建 Agent评分 60mNetworkAgentnewWifiNetworkAgent(getHandler().getLooper(),mContext,WifiNetworkAgent,mNetworkInfo,mNetworkCapabilitiesFilter,mLinkProperties,60,mNetworkMisc);// ConnectedState — 更新链路属性voidupdateLinkProperties(LinkPropertiesnewLp){mLinkPropertiesnewLp;if(mNetworkAgent!null){mNetworkAgent.sendLinkProperties(mLinkProperties);// 通知 ConnectivityService}}}关键设计WifiNetworkAgent在 L2ConnectedState二层已关联就创建此时还没有 IP。进入 ConnectedStateDHCP 完成后才调用sendLinkProperties更新 IP 信息。这是因为ConnectivityService需要先知道网络存在再逐步更新属性。阶段五网络验证NetworkMonitor向http://connectivitycheck.android.com/generate_204发 HTTP 请求。收到 204 响应 → 网络正常 →NetworkAgent添加NET_CAPABILITY_VALIDATED→ConnectivityService触发rematchAllNetworksAndRequests()进行评分比较。重定向 → 可能为 Captive Portal通知用户登录。2.3 WiFi 断开wpa_supplicant 检测信号丢失 ↓ WifiStateMachine 收到 DISCONNECTED → 进入 DisconnectedState ↓ mNetworkAgent.sendNetworkInfo(mNetworkInfo) ← 通知 ConnectivityService ↓ ConnectivityService 收到 NETWORK_LOST → rematchAllNetworksAndRequests() ↓ WiFi 从默认网络移除移动数据如果有接管三、移动数据连接3.1 架构概览移动数据连接的层级与 WiFi 不同DcTrackerHandler管理DataConnectionNetworkAgent实例每个 APN 类型一个连接。DataConnection通过RILJ→RILCrild→ Modem 与基站交互。┌─────────────────────────────────────────────────┐ │ ConnectivityService │ │ ↑ │ │ DataConnection (NetworkAgent) │ │ score50, TRANSPORT_CELLULAR │ ├─────────────────────────────────────────────────┤ │ DcTracker │ │ ┌─────────────────────────────────────────┐ │ │ │ DataConnection 池 │ │ │ │ default → DataConnection[0] │ │ │ │ supl → DataConnection[1] │ │ │ │ mms → DataConnection[2] │ │ │ └─────────────────────────────────────────┘ │ └──────────────────────┬──────────────────────────┘ │ RILJ → RILC (rild) → Modem源码路径frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.javapublicclassDcTrackerextendsHandler{// DataConnection 池keyid, valueDataConnection 实例privateHashMapInteger,DataConnectionmDataConnectionsnewHashMap();// 异步通道池keyid, valueDcAsyncChannelprivateHashMapInteger,DcAsyncChannelmDataConnectionAcHashMapnewHashMap();}关键设计DcTracker不直接持有NetworkAgent而是管理DataConnection池。每个DataConnection继承NetworkAgentDcTracker通过DcAsyncChannel与DataConnection异步通信实现连接复用——多个 APN 类型可共享同一个DataConnection。3.2 连接三阶段阶段一APN 配置加载ApnContext封装 APN 配置如 cmnet → typedefault,suplDcTracker根据 APN 类型决定是否发起连接。阶段二setupData → Modem 激活源码路径frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.javapublicclassDcTrackerextendsHandler{privatebooleansetupData(ApnContextapnContext,intradioTech){ApnSettingapnSettingapnContext.getNextApnSetting();if(apnSettingnull)returnfalse;// 1. 优先复用已有连接多 APN 共享同一 DataConnectionDcAsyncChanneldcaccheckForCompatibleConnectedApnContext(apnContext);if(dcac!null){apnSettingdcac.getApnSettingSync();// 复用连接}// 2. 无可用连接 → 创建新的 DataConnectionif(dcacnull){dcacfindFreeDataConnection();// 查找空闲连接if(dcacnull){dcaccreateDataConnection();// 创建新连接}}// 3. DataConnection 通过 RILJ 向 Modem 发送 SETUP_DATA_CALL// 返回 DataCallResponsermnet_data0、IP、网关、DNS}}关键设计setupData三步策略——先尝试复用已有连接checkForCompatibleConnectedApnContext再查找空闲连接findFreeDataConnection最后创建新连接createDataConnection。这种三级复用机制避免了为每个 APN 类型单独拨号。阶段三DataConnection 注册为 NetworkAgentDataConnection继承自NetworkAgent构建LinkProperties接口 rmnet_data0、IP、路由、DNS和NetworkCapabilitiesTRANSPORT_CELLULAR、INTERNET通过父类NetworkAgent机制向ConnectivityService注册评分 50。3.3 连接断开Modem 报告数据连接丢失 ↓ RIL 收到 UNSOLICITED_DATA_CALL_LIST_CHANGED ↓ DcTracker 处理 DEACTIVATE → DataConnection.tearDown() ↓ NetworkAgent.unregister() → ConnectivityService 重新评分四、以太网连接4.1 架构以太网是三种网络中最简单的——EthernetNetworkFactory监听内核 uevent 事件网线插入后自动启用接口并获取 IP。内核 uevent: add/devices/platform/eth0 ↓ EthernetNetworkFactory.maybeTrackInterface(eth0) ↓ setInterfaceUp(eth0) ← 通过 NMS 启用接口 ↓ DHCP 或静态 IP 配置 ↓ 创建 NetworkAgent (score70) → 自动成为默认网络最高分4.2 DHCP 模式源码路径frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.javaclassEthernetNetworkFactory{privateINetworkManagementServicemNMService;// 网络管理服务privateNetworkAgentmNetworkAgent;privateStringmIface;// 当前接口名如 eth0privateStringmIfaceMatch;// 接口匹配正则如 eth\\d// 正则匹配接口名避免误处理非以太网接口privatebooleanmaybeTrackInterface(Stringiface){if(!iface.matches(mIfaceMatch)||isTrackingInterface())returnfalse;setInterfaceUp(iface);// → mNMService.setInterfaceUp(iface)returntrue;}// DHCP 成功后调用向 ConnectivityService 上报publicvoidupdateAgent(){if(mNetworkAgentnull)return;mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);mNetworkAgent.sendNetworkInfo(mNetworkInfo);mNetworkAgent.sendLinkProperties(mLinkProperties);}}DHCP 成功后回调onIpConfigurationCompleted→ 构建NetworkCapabilitiesTRANSPORT_ETHERNET、INTERNET、NOT_METERED→ 创建NetworkAgent评分 70。4.3 静态 IP 模式跳过 DHCP直接通过 NMS 设置接口地址privatebooleansetStaticIpAddress(StaticIpConfigurationstaticConfig){InterfaceConfigurationconfigmNMService.getInterfaceConfig(mIface);config.setLinkAddress(staticConfig.ipAddress);// 设置 IPmNMService.setInterfaceConfig(mIface,config);// 写入接口returntrue;}关键设计静态 IP 模式跳过 DHCP 四步交互直接通过mNMService.setInterfaceConfig设置接口地址适用于无 DHCP 服务器的局域网环境。4.4 网络抢占以太网评分 70 WiFi 60 移动数据 50。网线插入后以太网NetworkAgent自动成为默认网络WiFi 进入 Linger 暂缓状态30 秒后拆除或降级。五、三种网络对比维度WiFi移动数据以太网连接触发AP 扫描运营商注册网线插入 uevent核心模块WifiStateMachine wpa_supplicantDataConnection RILEthernetNetworkFactory获取 IPDHCP (DhcpClient)Modem 分配DHCP / 静态评分605070TransportTRANSPORT_WIFITRANSPORT_CELLULARTRANSPORT_ETHERNET接口名wlan0rmnet_data0eth0计费否是否VPN 评分为 101但通过 RouteController 的 fwmark 优先级10000-12000覆盖而非竞争普通网络。六、网络验证的共性流程三种网络建立连接后都通过NetworkMonitor验证互联网可达性。这是防止已连接但无法上网的关键机制。源码路径frameworks/base/services/core/java/com/android/server/connectivity/NetworkMonitor.javapublicclassNetworkMonitorextendsStateMachine{// 验证流程// 1. HTTP GET http://connectivitycheck.android.com/generate_204// 2. 收到 204 → 网络正常 → 添加 NET_CAPABILITY_VALIDATED// 3. 收到重定向 → 可能为 Captive Portal → 通知用户登录// 4. 超时/失败 → 未验证 → 不选为默认网络}NetworkAgent 注册到 ConnectivityService ↓ ConnectivityService 启动 NetworkMonitor ↓ HTTP 探测 → 三种结果 ├── 204 响应 → VALIDATED → 可成为默认网络 ├── 重定向 → Captive Portal → 通知用户 └── 超时/失败 → 不验证 → 仅作备用网络七、关键源码文件索引文件路径本文涉及内容WifiStateMachine.javaframeworks/opt/net/wifi/service/java/com/android/server/wifi/状态机构建、WifiNetworkAgent 创建DhcpClient.javaframeworks/base/services/net/java/android/net/dhcp/DHCP 四步交互、指数退避DcTracker.javaframeworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DataConnection 池管理、setupData 三级复用EthernetNetworkFactory.javaframeworks/opt/net/ethernet/java/com/android/server/ethernet/uevent 监听、DHCP/静态 IP、NetworkAgentNetworkMonitor.javaframeworks/base/services/core/java/com/android/server/connectivity/HTTP 204 验证、Captive Portal 检测八、小结三种网络建立流程虽有差异但都遵循同一模式触发连接 → 获取 IP → 构建属性 → 注册 NetworkAgent → 验证 → 评分竞争理解这个统一模式后排查任何网络问题只需定位到对应阶段扫描不到 AP → 阶段一wpa_supplicantDHCP 超时 → 阶段三DhcpClientAPN 不对 → 阶段一ApnContext网线插了没反应 → uevent 监听EthernetNetworkFactory。下一篇将进入应用 API 层展示如何使用ConnectivityManager和实战调试。