本文介绍了 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 网络的信号范围时,该网络的质量会下降。如果有另一个不带此标志的网络可用,Android 会避免使用带有此标志的网络。每个网络代理都可以确定网络何时会降级到可以被视作退出的状态。
NetworkScore
类还允许网络代理使用 KEEP_CONNECTED_FOR_HANDOVER
标志和 NetworkScore.Builder.setKeepConnectedReason
方法声明某个网络会保持畅通。这个 KEEP_CONNECTED_FOR_HANDOVER
标志对潜在的网络很有用,它允许网络代理在次要 Wi-Fi STA 上建立一个网络,而不把它作为主要网络,直到完成网络性能评估为止。如果网络代理未声明此标志,则在代理有机会评估网络性能之前,潜在的网络会因为没有处理任何请求而被断开。
如果两个网络都可以处理指定请求,并且从政策的角度来看是等效的,Android 会优先选择当前正在处理该请求的网络。如果没有任何网络在处理请求,Android 会选择其中一个网络。之后,Android 将继续优先选择此网络,直至政策标志发生改变。
网络选择功能的实现位于 AOSP 的 Connectivity 模块中。网络选择的政策逻辑位于 NetworkRanker
类及其辅助类中。这意味着设备制造商无法直接自定义网络选择代码,而必须使用 NetworkScore
中的标志来传达有关网络的必要信息。
Android 11
对于搭载 Android 11 或更低版本的设备,Android 会根据通过网络代理 (NetworkAgent
) 实现发送的简单整数来执行网络选择。对于每个请求,Android 会选择能够满足请求且得分最高的网络。这个数字得分由网络代理发送的整数加上根据多个条件(如网络是否经过验证或者网络是否是 VPN)给予的额外加分或罚分组成。各个网络代理会相互同步,以便制定政策决策。
如果两个网络都可以处理指定请求,并且具有相同的数字得分,相应行为暂未定义。
NetworkScore 类
网络选择功能的核心类是 NetworkScore
。这个类包含可用标志和 setKeepConnectedReason
方法的相应 API 和文档。
NetworkScore
类必须通过其构建器类构建,并在初始化时传递给 NetworkAgent
构造函数。您可以使用 NetworkAgent#sendNetworkScore
方法随时更新网络得分。
网络代理实现示例
AOSP 包含各种网络代理的示例实现。以下是一些示例实现:
TelephonyNetworkAgent
:使用网络得分传达移动网络政策。ClientModeImpl.WifiNetworkAgent
:使用网络得分传达 Wi-Fi 网络政策。此实现向后兼容使用了POLICY_EXITING
标志的网络得分旧版整数。
升级到 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 设备上验证网络选择的行为,请使用以下测试:
NetworkScoreTest
CTS 测试NetworkRanker
单元测试
如果实现不正确,可能会导致应用因使用 NetworkCallback
而获得意外的网络,包括选择设备的默认网络(系统在应用使用 ConnectivityManager.registerDefaultNetworkCallback
的网络回调时发送给应用的网络)。
不正确实现可能导致的另一个问题是,网络代理启动时,其得分不符合任何请求的条件,而后立即被关闭,这就造成了严重的电量消耗。如果代理反复启动和关闭,这可能会消耗大量电量。