一、总体介绍
(一)功能
手动搜网的流程:用户通过UI触发,调用TelephonyManager的API,比如startNetworkScan,然后这个请求会传递到RIL层,通过AT命令与基带通信,进行网络扫描。结果返回后,经过TelephonyRegistry通知应用层。中间可能涉及IPC,比如Binder通信,因为应用和系统服务运行在不同的进程。
自动搜网的流程:由系统服务如ConnectivityService或NetworkPolicyManager根据网络状态变化(如信号强度变化)触发,调用相应的模块进行评估,比如根据信号强度、优先级策略等选择最佳网络,然后通过RIL层切换网络。可能用到NetworkSelection模块,评估网络质量,计算得分,然后切换。
Note:以上是一般情况。
异常处理:
- 手动模式超时:
EVENT_GET_OPERATOR_LIST_COMPLETE
未响应时触发onError(Callback.ERROR_TIMEOUT)
- 自动模式降级策略:当首选PLMN不可用时,按
RSSI阈值
自动切换至次优网络 - Modem异常捕获:通过
RILReceiver线程
监控Socket连接状态
(二)需求
运营商需求:当SIM卡设置中选择了自动搜网,那么在重启开机后要执行一次手动搜网。而手动搜网且驻网失败时会自动切换的自动搜网。
开发方案问题:若基于本身单卡的实现,只搜索卡槽0的,而且写成了单线程,那么就在适配双卡的过程中还需要调整设计模式。那么AOSP双卡搜网逻辑是怎样的呢?或许没有这种开机的需求,就不存在问题。
Note:以下基于 Android 14 源码逻辑分析,不同 Android 版本实现细节可能存在差异。
(三)交互方式
- 中间件交互方式主要包括Binder、HIDL(HAL 接口定义语言)/AIDL接口,因为Android的框架层和底层服务通过这些IPC机制跨进程通信。
- 参考文章:使用 binder IPC | Android Open Source Project。
- 从 Android 8 开始,Android 框架和 HAL (Hardware Abstract Layer)现在使用 Binder 互相通信。
- 由于这种通信方式极大地增加了 Binder 流量,因此 Android 8 包含了几项改进,旨在确保 Binder IPC 的速度。SoC 供应商和原始设备制造商 (OEM) 应直接从 android-4.4、android-4.9 及更高版本内核/通用项目的相关分支进行合并。
-
使用 Binder IPC
一直以来,供应商进程都使用 Binder 进程间通信 (IPC) 技术进行通信。在 Android 8 中,
/dev/binder
设备节点成为框架进程的专有节点,这意味着供应商进程无法再访问此节点。供应商进程可以访问/dev/hwbinder
,但必须将其 AIDL 接口转为使用 HIDL。对于想要继续在供应商进程之间使用 AIDL 接口的供应商,Android 会按以下方式支持 Binder IPC。 在 Android 10 中,稳定的 AIDL 允许所有进程使用/dev/binder
,同时还力求解决 HIDL 和/dev/hwbinder
已解决的稳定性保证。如需了解如何使用 Stable AIDL,请参阅适用于 HAL 的 AIDL。
- 命令方面,RIL层可能使用AT命令
- 比如AT+COPS用于运营商选择。
- 传输方式可能通过socket或RILD与modem通信。RIL使用socket与modem通信,而框架层使用Binder。
- rild:旧版基于Socket,新版逐步转向HIDL(Binder)。Android 8 之前还是socket。
- netd:核心功能依赖Socket(Netlink + 本地Socket),辅助使用Binder。
- 是否“属于Socket通信”?架构对比:
- 传统架构:两者均重度依赖Socket。(RIL.java -> ril.cpp)
- 现代架构:rild部分功能迁移至Binder(RIL.java -> ril_service.cpp),netd仍以Socket为主。
如下图,Android 8(Orea,包含8.0和8.1)之前Telephony与modem之间使用socket通信,属于RILD;Android 8之后使用HIDL通信。


Note:可以专门一篇文章介绍通信方式的代码变更。
(四)功能相关核心模块
模块/组件 | 职责 | 关键类/接口 |
---|---|---|
TelephonyManager | 对外API暴露 | TelephonyManager.java |
ServiceStateTracker | 网络状态跟踪 | ServiceStateTracker.java |
RIL (Radio Interface) | 与Modem通信的HAL层 | RIL.java , RILRequest.cpp |
NetworkPolicyManager | 策略管理 | NetworkPolicyManagerService |
CarrierConfigLoader | 加载运营商策略 | CarrierConfigManager.java |
(五)关键传输协议
-
AT命令协议
- 手动搜网:
AT+COPS=?
(查询运营商列表) - 自动选网:
AT+COPS=0
(启用自动模式)
- 手动搜网:
-
RIL协议定义
- 请求类型:
RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
- 异步事件:
RIL_UNSOL_NETWORK_STATE_CHANGED
- 请求类型:
- Binder接口
// ITelephony.aidl
interface ITelephony {List<NetworkInfo> getAvailableNetworks();void setNetworkSelectionModeAutomatic();
}
二、Android设计思想
(一)网络选择 Roadmap
参考文档:网络选择 | Android Open Source Project(本部分介绍了搭载 Android 12 或更高版本的设备以及搭载 Android 11 及更低版本的设备的网络选择行为。)
对于搭载 Android 12 或更高版本的设备,Android 使用 NetworkScore 类在可用网络之间进行选择。这个类包含制定政策决策所需的许多标志。在语义上,每个标志均表示对网络选择而言非常重要的一个网络属性。
网络代理 (NetworkAgent) 使用 POLICY_TRANSPORT_PRIMARY 标志指明当同一传输中存在多个网络时,相应网络是首选。一个典型的示例就是双 SIM 卡设备,其“设置”中设有一个切换开关,可供用户选择默认使用哪张 SIM 卡。在指定的传输中,Android 倾向于选择带有 POLICY_TRANSPORT_PRIMARY 标志的网络,而不是没有该标志的网络。
网络代理使用 POLICY_EXITING 标志来识别预计很快会断开连接的网络。一个典型的示例就是,当用户走出某个 Wi-Fi 网络的信号范围时,该网络的质量会下降。如果有另一个不带此标志的网络可用,Android 会避免使用带有此标志的网络。每个网络代理都可以确定网络何时会降级到可以被视作退出的状态。
NetworkScore类还允许网络代理(network agent) 使用 KEEP_CONNECTED_FOR_HANDOVER 标志和 NetworkScore.Builder.setKeepConnectedReason 方法声明某个网络会保持畅通。这个 KEEP_CONNECTED_FOR_HANDOVER 标志对潜在的网络很有用,它允许网络代理在次要 Wi-Fi STA 上建立一个网络,而不把它作为主要网络,直到完成网络性能评估为止。如果网络代理未声明此标志,则在代理有机会评估网络性能之前,潜在的网络会因为没有处理任何请求而被断开。
如果两个网络都可以处理指定请求(Note:在Android 11中,以上并且具有相同的数字得分,相应行为暂未定义。),并且从政策的角度来看是等效的,Android 会优先选择当前正在处理该请求的网络。如果没有任何网络在处理请求,Android 会选择其中一个网络。之后,Android 将继续优先选择此网络,直至政策标志发生改变。
网络选择功能的实现位于 AOSP 的 Connectivity 模块中。网络选择的政策逻辑位于 NetworkRanker 类及其辅助类中。这意味着设备制造商无法直接自定义网络选择代码,而必须使用 NetworkScore 中的标志来传达有关网络的必要信息。
Conectiivity 是 Google Mainline的模块,OEM不能修改其内逻辑。
对于搭载 Android 11 或更低版本的设备,Android 会根据通过网络代理 (NetworkAgent) 实现发送的简单整数来执行网络选择。对于每个请求,Android 会选择能够满足请求且得分最高的网络。这个数字得分由网络代理发送的整数加上根据多个条件(如网络是否经过验证或者网络是否是 VPN)给予的额外加分或罚分组成。各个网络代理会相互同步,以便制定政策决策。</