Wi-Fi STA/STA Concurrency

Android 12 introduces Wi-Fi STA/STA concurrency, which allows devices to connect to two Wi-Fi networks concurrently. This optional feature enables the following functions.

  • Make-before-break: The device makes a connection to a new Wi-Fi network before breaking the existing connection. This results in smoother transitions when switching between Wi-Fi networks
  • Concurrent local-only and internet connection: The device connects to a local-only network without disrupting the device's primary internet-providing connection.
  • Concurrent restricted and internet connection: The device connects to a restricted network (available only to certain privileged apps) without disrupting the device's primary internet-providing connection.

This page describes the device behavior when this feature is enabled and the implementation details for device manufacturers and vendors.

Implementation

Devices must support the following in order to implement Wi-Fi STA/STA concurrency:

  • The Wi-Fi chip or firmware must support two concurrent STA connections. The firmware must support all channel and band combinations for both connections. To avoid performance issues, we recommend using a 2x2+2x2 DBS capable Wi-Fi chip.

  • The device must support the following APIs in vendor HAL version 1.5

    • IWifiChip.setMultiStaPrimaryConnection()
    • IWifiChip.setMultiStaUseCase()
  • The HAL Wi-Fi interface combination must have two concurrent STA interfaces exposed using a specifaction format such as [{STA} <= 2, ...]. For more information, see Wi-Fi multi-interface concurrency.

If those pre-requisites are met, implement Wi-Fi STA/STA concurrency by doing the following:

  1. Enable one or more function individually using runtime resource overlays (disabled by default).

    • Make-before-break: config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled
    • Concurrent local-only and internet connection: config_wifiMultiStaLocalOnlyConcurrencyEnabled
    • Concurrent restricted and internet connection: config_wifiMultiStaRestrictedConcurrencyEnabled
  2. Validate each implementation as described in their respective sections below.

To better support Wi-Fi STA/STA concurrency, we recommend that OEM-customized frameworks and apps use the NetworkCallback#onCapabilitiesChanged() method instead of WifiManager#getConnectionInfo(), which only returns WifiInfo for a single network and was deprecated in Android 12. For more information, see Wi-Fi Network Request API for peer-to-peer connectivity.

Make-before-break

The make-before-break function allows devices to connnect to a new Wi-Fi network while maintaining the existing Wi-Fi network connection, only disconnecting from the old network when it successfully connects to the new Wi-Fi network and has internet access.

The make-before-break use case addresses the following problems in Android 11 or lower, where the device must disconnect from the existing Wi-Fi network before connecting to a new network (break-before-make).

  • When connecting to a new network, the device might discover that it has an incorrect Wi-Fi password saved or that the new network doesn't have internet access. This forces the device to switch back to the old network, leading to a signifcant amount of time without Wi-Fi connectivity.

  • The old network is disconnected abruptly, which means that all sockets get closed. Apps often don't react well to a sudden loss of connectivity and this might lead to the user experiencing a few seconds without internet connectivity until the new connection is fully established.

  • The default network changes twice, from the old Wi-Fi network to cellular, then from cellular to the new Wi-Fi network. This causes apps to react to network changes twice. The device must also spend a short amount of time using cellular data.

The make-before-break flow is only used for automatic Wi-Fi network switches initiated by the OS. User-initiated network switches use the legacy break-before-make flow, where the previous network is fully disconnected before the new network is connected. In certain cases, the break-before-make flow is used even in automatic switches initiated by the OS, for example, when switching between two networks both configured to use the factory MAC address.

Apps can check whether this use case is supported on the device using the WifiManager#isMakeBeforeBreakWifiSwitchingSupported() API.

Validating make-before-break

To validate your implementation, trigger an automatic Wi-Fi network switch (by ensuring a network with a stronger signal strength than the currently connected network is available) and verify that the device maintains the existing connection while connecting to the new network. To view the status of both Wi-Fi interfaces and verify that both are connected, use the following command.

adb shell wpa_cli -i wlan0 status ; echo ; adb shell wpa_cli -i wlan1 status

If the new network doesn't have connectivity, the device attempts to connect to the network, while maintaining the connection with the existing network, and aborts the attempt when it detects the new network doesn't have internet. The device then continues using the existing connection as the primary Wi-Fi network.

Concurrent local-only and internet connection

The concurrent local-only and internet connection function allows devices to connect to a local-only conection, such as a connection to an IoT device, concurrently with the primary internet-providing network. This function improves the user experience when directly connecting to IoT devices, such as cameras, which is possible through the WifiNetworkSpecifier API added in Android 10.

In Android 11 and lower, devices disconnect from the primary Wi-Fi network when connecting to an IoT device, resulting in a loss of internet connectivity (unless the device has another transport type available, such as cellular data).

Apps can check whether this function is supported on the device using the WifiManager#isStaConcurrencyForLocalOnlyConnectionsSupported() API.

For more information on changes to the concurrent local-only and internet connection function in Android 12, see Wi-Fi Network Request API for peer-to-peer connectivity.

Validating local-only and internet connection

To validate this function, use the following CTS and ACTS tests:

  • CTS: MultiStaConcurrencyWifiNetworkSpecifierTest
  • ACTS: WifiStaConcurrencyNetworkRequestTest

Concurrent restricted and internet connection

The concurrent restricted and internet connection function allows the device to conccurently connect to a primary Wi-Fi network for the user and a restricted Wi-Fi network that is only available to select apps.

Apps can check whether this function is supported on the device using the WifiManager#isStaConcurrencyForRestrictedConnectionsSupported() API.

To enable a device to connect to secondary restricted Wi-Fi networks, follow these steps:

  1. Add Wi-Fi network suggestions with setOemPaid or setOemPrivate set to true.

  2. In ConnectivityManager, file a NetworkRequest with the corresponding capabilities:

When the device detects scan results with a network matching the OEM paid or OEM private suggestion, it automatically connects to it as a secondary network.

Validating concurrent restricted and internet connection

To validate this function, use the following CTS and ACTS tests:

  • CTS: MultiStaConcurrencyRestrictedWifiNetworkSuggestionTest
  • ACTS: WifiStaConcurrencyNetworkRequestTest

Vendor Wi-Fi chip guidelines

For Wi-Fi chip vendors, use the following guidelines to support Wi-Fi STA/STA concurrency.

The Wi-Fi chip must support dual concurrent STA connections. This means it supports the following:

  • Each STA interface has a unique MAC programmable by the framework.
  • The secondary STA interface can be dynamically created and destroyed.
  • Each STA can be connected to a different SSID (either within the same band or a different band).
  • Each STA can be connected to the same SSID (either within the same band or a different band). The two STAs must never be connected to the same BSSID.

Critical features must operate on a per-interface basis and they must be available on the primary interface. The following is a list of these critical features:

  • Roaming must be supported on at least the primary interface (set using IWifiChip.setMultiStaPrimaryConnection()). If roaming is suppported on both interfaces, decisions on one connection must not clash with the second concurrent connection. For example, one interface must not roam to the BSSID of the other connection.

  • APF (and other offloads such as ARP and NS) must be supported on at least the primary interface (set using IWifiChip.setMultiStaPrimaryConnection()).

  • Link layer stats must operate on a per interface basis.

The following are recommended Wi-Fi chip implementations for different concurrency scenarios:

  • The Wi-Fi chip must allow the framework to call IWifiChip.setMultiStaUseCase() with one of the following constants to specify the current function:

    • DUAL_STA_TRANSIENT_PREFER_PRIMARY: Specifies the Make-Before-Break function. The quality of the primary connection must be prioritized over the secondary connection.
    • DUAL_STA_NON_TRANSIENT_UNBIASED: Specifies the concurrent local-only and internet connection or the concurrent restricted and internet connection function. The quality of both connections must be prioritized equally.
  • Because dual concurrent STAs can lead to MCC, SCC, and DBS modes of operation, the vendor implementation must choose the best radio configuration when the framework calls IWifiChip.setMultiStaUseCase() to indicate the function. The following are general guidelines:

    • 2x2+2x2 DBS is preferred if available.
    • Avoid 1x1+1x1 DBS if possible because of the excessive impact on connection quality. Instead, prefer MCC.
    • The MCC duty cycle must be configurable by the driver or firmware for the various functions. The framework doesn't set the MCC duty cycle directly, but queries this information using StaLinkLayerIfaceStats.timeSliceDutyCycleInPercent.
    • If using MCC, we recommend the following duty cycles between the primary and secondary connections:

      • DUAL_STA_TRANSIENT_PREFER_PRIMARY: 70% primary, 30% secondary.
      • DUAL_STA_NON_TRANSIENT_UNBIASED: 50% primary, 50% secondary.