Network Selection

This page describes how Android selects between concurrently available networks. This network selection mechanism affects how Android fulfills app and system network requests, and influences how the default network for an app is chosen.

Network selection behavior

This section describes the network selection behavior for devices running Android 12 or higher and for devices running Android 11 and lower.

Android 12

For devices running Android 12 or higher, Android uses the NetworkScore class to select between available networks. This class contains a number of flags required to make policy decisions. Each flag semantically represents an attribute of a network that's important for network selection.

A network agent (NetworkAgent) uses the POLICY_TRANSPORT_PRIMARY flag to specify that the network is preferred when multiple networks of the same transport are present. A typical example of this is a dual-SIM device with a switch in Settings to let the user choose which of the SIM cards to use by default. Within a given transport, Android prefers a network with the POLICY_TRANSPORT_PRIMARY flag over a network without the flag.

A network agent uses the POLICY_EXITING flag to identify a network that is expected to disconnect soon. A typical example of this is when a Wi-Fi network quality degrades as a user walks out of range of the network. Android avoids using a network with this flag if another network without this flag is available. Each individual network agent can determine when a network degrades enough to be considered exiting.

The NetworkScore class also allows a network agent to declare that a network be kept up using the KEEP_CONNECTED_FOR_HANDOVER flag and the NetworkScore.Builder.setKeepConnectedReason method. This KEEP_CONNECTED_FOR_HANDOVER flag is useful for prospective networks allowing a network agent to bring up a network on a secondary Wi-Fi STA without making it the primary network until the network's performance is evaluated. If a network agent doesn't declare this flag, prospective networks are torn down for not servicing any request before the agent has a chance to evaluate a network's performance.

If two networks can serve a given request and are equivalent from a policy point of view, the selection prefers the network that is currently serving the request. If no network is serving the request, it chooses one of the two, after which this network continues to be preferred until policy flags change.

The implementation for the network selection feature is in the Connectivity module in AOSP. The policy logic for network selection is found in the NetworkRanker class and its helper classes. This means that device manufacturers can't directly customize the network selection code but instead must use the flags in NetworkScore to convey required information about networks.

Android 11

For devices running Android 11 or lower, Android performs network selection based on a simple integer sent from the implementations of a network agent (NetworkAgent). For each request, Android selects the network with the highest numeric score that can satisfy the request. This numeric score is composed of the integer sent by the network agent plus additional bonuses or penalties given based on a number of conditions such as whether the network is validated or whether the network is a VPN. Individual network agents synchronize with each other in order to make policy decisions.

If two networks can serve a given request and have the same numeric score, the behavior is undefined.

NetworkScore class

The central class for the network selection feature is NetworkScore. This class contains the API and documentation of the available flags and the setKeepConnectedReason method.

The NetworkScore class must be built through its builder class and be passed to the NetworkAgent constructor upon initialization. Network scores can be updated at any time using the NetworkAgent#sendNetworkScore method.

Network agent implementation examples

AOSP includes example implementations of various network agents. The following are example implementations:

  • TelephonyNetworkAgent: Uses network score to communicate policy for mobile networks
  • ClientModeImpl.WifiNetworkAgent: Uses network score to communicate policy for Wi-Fi networks. This implementation includes backward compatibility with the legacy integer for network score using the POLICY_EXITING flag.

Devices upgrading to Android 12

Device manufacturers upgrading their devices to Android 12 must modify their network agent implementations to use the NetworkScore class. The legacy integer used in Android 11 or lower is passed in NetworkScore but is only used for logging and non-regression purposes in Android 12. In Android 12, device manufacturers must express desired changes using NetworkScore flags. The Connectivity Mainline module then uses the flags to make the network selection decision. Devices manufacturers using code for Android 11 or lower but building against the implementation in Android 12 can expect build errors as the methods for updating the legacy integer were removed in Android 12.

For network agents that use the internal NetworkFactory class, they must express their score filter in a NetworkScore object representing the strongest score of a network the factory can create. This is because in Android 12 the NetworkFactory class only passes requests that match the score filters declared to NetworkFactory instead of all requests in Android 11 and lower.

We recommend passing a filter for easier implementation and battery savings so that not all requests are passed to NetworkFactory. However, if your custom implementation requires that all requests be passed to NetworkFactory, you can register NetworkFactory.registerIgnoringScore instead of the regular NetworkFactory.register method. If using this method, we recommend passing a score filter that represents most accurately the best score the factory can create in order to save battery by not evaluating requests that the factory can't fulfill.

Validation

To verify the behavior of network selection on an Android device, use the following tests:

Incorrect implementation might result in unexpected networks being returned to apps in response to their use of NetworkCallback, including selecting the default network of the device (the network the system sends to the app when they use a network callback with ConnectivityManager.registerDefaultNetworkCallback).

Another possible issue with incorrect implementation is severe battery drain caused by a network agent being brought up with a score that doesn't let it qualify for any request and being torn down immediately after. If the agent is brought up and torn down repeatedly, this could use up a lot of battery.