网络选择

本页面介绍了 Android 如何在并发可用的网络之间进行选择。这种网络选择机制会影响 Android 如何满足应用和系统网络请求,并影响如何为应用选择默认网络。

网络选择行为

本部分介绍了运行 Android 12 或更高版本的设备以及运行 Android 11 及更低版本的设备的网络选择行为。

Android 12

对于运行 Android 12 或更高版本的设备,Android 使用 NetworkScore 类在可用网络之间进行选择。此类包含许多进行政策决策所需的标志。每个标志在语义上都表示对网络选择而言很重要的网络属性。

网络代理 (NetworkAgent) 使用 POLICY_TRANSPORT_PRIMARY 标志来指定当存在同一传输类型的多个网络时,首选该网络。一个典型的例子是双 SIM 卡设备,设置中有一个开关,让用户选择默认使用哪个 SIM 卡。在给定的传输类型中,Android 优先选择具有 POLICY_TRANSPORT_PRIMARY 标志的网络,而不是没有该标志的网络。

网络代理使用 POLICY_EXITING 标志来标识预计很快断开连接的网络。一个典型的例子是当用户走出 Wi-Fi 网络范围时,Wi-Fi 网络质量下降。如果另一个没有此标志的网络可用,Android 会避免使用带有此标志的网络。每个单独的网络代理都可以确定网络何时降级到足以被视为正在退出。

NetworkScore 类还允许网络代理声明使用 KEEP_CONNECTED_FOR_HANDOVER 标志和 NetworkScore.Builder.setKeepConnectedReason 方法来保持网络连接。KEEP_CONNECTED_FOR_HANDOVER 标志对于前瞻性网络非常有用,它允许网络代理在辅助 Wi-Fi STA 上启动网络,而无需使其成为主网络,直到评估网络的性能为止。如果网络代理未声明此标志,则前瞻性网络会因在代理有机会评估网络性能之前未服务任何请求而被拆除。

如果两个网络都可以服务给定的请求,并且从策略角度来看是等效的,则选择当前正在服务请求的网络。如果没有网络正在服务请求,则选择其中一个网络,之后,在策略标志更改之前,将继续首选此网络。

网络选择功能的实现在 AOSP 的 Connectivity 模块中。网络选择的策略逻辑位于 NetworkRanker 类及其辅助类中。这意味着设备制造商无法直接自定义网络选择代码,而必须使用 NetworkScore 中的标志来传达有关网络的所需信息。

Android 11

对于运行 Android 11 或更低版本的设备,Android 会根据网络代理 (NetworkAgent) 的实现发送的简单整数来执行网络选择。对于每个请求,Android 会选择可以满足请求的最高数值评分的网络。此数值评分由网络代理发送的整数以及根据多种条件(例如网络是否已验证或网络是否为 VPN)给出的额外奖励或惩罚组成。各个网络代理相互同步,以便做出策略决策。

如果两个网络都可以服务给定的请求并且具有相同的数值评分,则行为未定义。

NetworkScore 类

网络选择功能的核心类是 NetworkScore。此类包含可用标志和 setKeepConnectedReason 方法的 API 和文档。

NetworkScore 类必须通过其构建器类构建,并在初始化时传递给 NetworkAgent 构造函数。可以使用 NetworkAgent#sendNetworkScore 方法随时更新网络评分。

网络代理实现示例

AOSP 包含各种网络代理的示例实现。以下是一些示例实现:

升级到 Android 12 的设备

将其设备升级到 Android 12 的设备制造商必须修改其网络代理实现以使用 NetworkScore 类。Android 11 或更低版本中使用的旧版整数在 NetworkScore 中传递,但在 Android 12 中仅用于日志记录和非回归目的。在 Android 12 中,设备制造商必须使用 NetworkScore 标志来表达所需的更改。然后,Connectivity Mainline 模块使用这些标志来做出网络选择决策。使用 Android 11 或更低版本的代码但针对 Android 12 中的实现进行构建的设备制造商可能会遇到构建错误,因为用于更新旧版整数的方法已在 Android 12 中删除。

对于使用内部 NetworkFactory 类的网络代理,它们必须在表示工厂可以创建的网络的最强评分的 NetworkScore 对象中表达其评分过滤器。这是因为在 Android 12 中,NetworkFactory 类仅传递与声明给 NetworkFactory 的评分过滤器匹配的请求,而不是 Android 11 和更低版本中的所有请求。

我们建议传递过滤器以简化实现并节省电池电量,以便并非所有请求都传递给 NetworkFactory。但是,如果您的自定义实现要求将所有请求都传递给 NetworkFactory,您可以注册 NetworkFactory.registerIgnoringScore 而不是常规的 NetworkFactory.register 方法。如果使用此方法,我们建议传递一个评分过滤器,该过滤器最准确地表示工厂可以创建的最佳评分,以便通过不评估工厂无法满足的请求来节省电池电量。

验证

要验证 Android 设备上网络选择的行为,请使用以下测试:

不正确的实现可能会导致意外的网络返回到应用,以响应其对 NetworkCallback 的使用,包括选择设备的默认网络(系统在应用使用带有 ConnectivityManager.registerDefaultNetworkCallback 的网络回调时发送给应用的那个网络)。

不正确实现的另一个可能问题是严重的电池电量消耗,这是由于网络代理以不让其有资格获得任何请求的评分启动,并在启动后立即被拆除。如果代理被重复启动和拆除,则可能会消耗大量电池电量。