How to change Wi-Fi device for Android

Revision as of 17:20, 22 August 2019 by Registered User (→‎Update the Linux device tree)

This article describes the integration steps required to connect your own Wi-Fi device. It deals mainly with the Android impact of integrating the new Wi-Fi solution. It is intended for Distribution Package users.

1. Prerequisite[edit source]

The environment must be installed using the Distribution Package adapted to your selected microprocessor device. See the list of Android Distribution Package.

The Wi-Fi device must be connected to the microprocessor device within your board.

2. Overview[edit source]

Android Wi-Fi Overview

The Android Wi-Fi software stack contains:

  • Wi-Fi Driver (hardware dependent) → device driver providing access to the Wi-fi hardware device through sockets of the netlink family (AF_NETLINK, nl80211 protocol).
  • Wi-Fi HALs (Hardware Abstraction Layer) → three HAL native components implementing the Android Wi-Fi HIDLs (Hardware Interface Definition Language). The optional Vendor HAL provides Android-specific commands, the Supplicant HAL provides HIDL access to the wpa_supplicant daemon and the Hostapd HAL provides HIDL access to the hostapd daemon.
  • Wi-Fi Connection Manager (wificond) → stand-alone daemon process managing the Wi-Fi connection. It is accessible through the binder IPC mechanism and communicates with the Wi-Fi driver using standard nl80211 commands.
  • Wi-Fi system services → several Android system services (WiFiService for Wi-Fi connection, WifiP2PService for Wi-Fi Direct™ connection, WifiAwareService for Wi-Fi Aware™ (Neighbour Awareness Networking protocol)...) implementing the Wi-Fi AIDLs (Android Interface Definition Language) in the process context of the System Server. These services interact with the native subsystem using the Wi-Fi HALs.
  • Framework Wi-Fi API → android.net.wifi APIs providing applications with framework level access to the Wi-Fi subsystem. Internally, the code uses client side Wi-Fi AIDLs to interact with the Wi-Fi system services container process through the Binder IPC mechanism.

Please see the Android Wi-Fi guide[1] for complementary information.

3. Integration steps[edit source]

The Wi-Fi solution must be integrated in three main steps:

  • Linux kernel integration
  • Android integration
  • Validation

3.1. Linux kernel integration[edit source]

The kernel Wi-Fi integration is performed in two steps:

  • Add the Wi-Fi driver within the compilation process
  • Update the device tree

3.1.1. Compile the Linux Wi-Fi driver[edit source]

The Wi-Fi subsystem is accessed through a nl80211 driver (netlink socket).

Two options:

  • The Wi-Fi driver is part of the Linux kernel source → select its config (ex: CONFIG_RTL8723BU=y for the Realtek RTL8723BU, for kernel version ≤ 4.9)
  • The Wi-Fi driver is provided separately → add it within the compilation process (see Updating the kernel configuration for more information)

3.1.2. Update the Linux device tree[edit source]

Depending on the driver selected, it can be required to update the device tree (refer to Changing the Device Tree for more information).

3.2. Android integration[edit source]

The Wi-Fi device integration within Android is performed in several steps:

  • Add properties to give information on the nl80211 interface available
  • Add permissions to allow starting the required Android services
  • Add the Wi-Fi interface (Hardware Abstraction Layer) if available for your Wi-Fi device
  • Add the Wi-Fi firmware if available for your Wi-Fi device
  • Configure the Wi-Fi supplicant

3.2.1. Add Android properties[edit source]

Two netlink interfaces can be set within Android through properties. For that purpose add in device.mk the following lines:

PRODUCT_PROPERTY_OVERRIDES += \
wifi.interface=wlan0
wifi.direct.interface=p2p0

Note: wlan0 and p2p0 are already the default netlink interfaces, it is not mandatory to set them

3.2.2. Add Android permissions[edit source]

Three permissions can be added to ensure that the Wi-Fi services are correctly started:

  • android.hardware.wifi.xml → start the Wi-Fi service
  • android.hardware.wifi.direct.xml → start the Wi-Fi Direct service
  • android.hardware.wifi.aware.xml → start the Wi-Fi Aware service

For that purpose, it is required to add the following lines within device.mk

PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.wifi.xml:system/etc/permissions/android.hardware.wifi.xml \
frameworks/native/data/etc/android.hardware.wifi.direct.xml:system/etc/permissions/android.hardware.wifi.direct.xml \
frameworks/native/data/etc/android.hardware.wifi.aware.xml:system/etc/permissions/android.hardware.wifi.aware.xml \

3.2.3. Add the Wi-Fi HAL (Hardware Abstraction Layer)[edit source]

The Wi-Fi Interface (HAL) must be integrated if any vendor extension is available → generate libwifi-hal-<device name>.so library

Examples of extension services: GSCAN (offload Scan), RTT (Round Trip Time), NAN (Neighbor Aware Networking), RSSI (offload Received Signal Strength Indication) or offload roaming (black list).

The BoardConfig.mk must be updated in consequence:

BOARD_WLAN_DEVICE := <device> → needed if specific wifi_hal is implemented (products available by default in framework/opt/net/wifi/service/Android.mk)

Your Wi-Fi device provider can also provide its own implementation and associated directives.

3.2.4. Add the Wi-Fi device firmware[edit source]

Depending on the Wi-Fi solution, it can be required to load a firmware within the device.

The firmware must be copied within the correct device directory, that can be configured through the kernel command line. For that purpose, add in BoardConfig.mk the following line:

 BOARD_KERNEL_CMDLINE += firmware_class.path=/etc/firmware/

The firmware must be added in the ramdisk (rootfs) to ensure that it is available during the first stage of initialization

PRODUCT_COPY_FILES += \
device/stm/<STM32Series>/<BoardId>/network/wifi/<wifi_firmware>.bin:root/system/etc/firmware/<wifi_path>/<wifi_firmware>.bin \
device/stm/<STM32Series>/<BoardId>/network/wifi/<wifi_firmware>.bin:system/etc/firmware/<wifi_path>/<wifi_firmware>.bin

Note: if the driver is compiled as a module (.ko) and loaded after the on post-fs tag, it is not required to add the firmware within the rootfs

Depending on your selected solution, you may have to reload a firmware dynamically. For example, depending on your selected solution, the following variable in BoardConfig.mk can be required:

WIFI_DRIVER_FW_PATH_STA := “<FW PATH>“ → used only if necessary, give specific FW for standard station configuration
WIFI_DRIVER_FW_PATH_P2P := “<FW PATH>“ → used only if necessary, give specific FW for standard peer to peer configuration
WIFI_DRIVER_FW_PATH_AP  := “<FW PATH>“ → used only if necessary, give specific FW for standard access point configuration

Your Wi-Fi device provider can also provide its own implementation and associated directives.

3.2.5. Configure the Android service[edit source]

The supplicant is started with two possible options (see wpa_supplicant(8) - Linux man page for more information):

  • wpa_supplicant (one driver interface: wlan0, one control interface: /data/misc/wifi/sockets) → in case of the wifi permission only
service wpa_supplicant /system/bin/wpa_supplicant \
   -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
   -I/system/etc/wifi/wpa_supplicant_overlay.conf -O/data/misc/wifi/sockets \
   -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0
  • p2p_supplicant (two driver interfaces: wlan0 and p2p0, one control interface: /data/misc/wifi/sockets) → in case of wifi and wifi.direct permissions
service p2p_supplicant /system/bin/wpa_supplicant \
   -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
   -I/system/etc/wifi/wpa_supplicant_overlay.conf -O/data/misc/wifi/sockets \
   -N -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \
   -I/system/etc/wifi/p2p_supplicant_overlay.conf \
   -puse_p2p_group_interface=1 \
   -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0

The BoardConfig.mk must be updated in consequence:

WPA_SUPPLICANT_VERSION := VER_0_8_X
BOARD_WPA_SUPPLICANT_DRIVER := NL80211
BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_$(BOARD_WLAN_DEVICE) → needed to define if any specific supplicant vendor library is available (stubbed by default)

You can find the current supplicant overlay in /device/stm/<STM32Series>/<BoardId>/network/wifi/:

  • wpa_supplicant_overlay.conf
disable_scan_offload=1  → used to disable the offloading (not available by default)
p2p_disabled=1 → used to disable the p2p mode (not required)
  • p2p_supplicant_overlay.conf
disable_scan_offload=1  → used to disable the offloading (not available by default)
p2p_search_delay=100  → used to limit the radio usage for p2p search action

3.3. Validation[edit source]

The Wi-Fi validation can be performed in several steps:

  • Validate Kernel integration
  • Validate Wi-Fi connection using standard Android user interface
  • Check Wi-Fi Android compliance (CTS)

3.3.1. Validate the Kernel Integration[edit source]

Reminder: the Wi-Fi subsystem is accessed through a netlink socket (nl80211). A tool named iw can be used to check its capabilities.

Open a device console executing:

 adb shell 

Examples of commands (see the iw man page[2] for more details):

 iw list → list all available information on nl80211 socket (incl supported ciphers and commands)
 iw wlan0 scan → scan operation (grep SSID to get only SSID)
 iw wlan0 connect <ssid> → connect to the defined SSID if not protected (otherwise wpa_supplicant shall be used)
 iw dev wlan0 link → give wlan0 connection state

3.3.2. Check the Wi-Fi connection[edit source]

Enable the Wi-Fi connection in Android Settings and try to connect to a known access point (see the Android One available answers for more information [3]).

3.3.3. Execute the Wi-Fi CTS tests[edit source]

In the Android top directory, execute:

 make cts

Go in out/host/linux-x86/cts/android-cts/tools/ directory and execute:

 ./cts-tradefed

It is recommended to execute at least "CtsNetTestCases" test suite:

 run cts --skip-preconditions --module CtsNetTestCases

For more information on the CTS execution, see the Android compatibility guide[4]

3.4. Debugging Tips[edit source]

It's possible to enable or disable the "Verbose" mode of the Wi-Fi framework (wificond) logging through the Settings menu: System->Developer options->Enable Wi-Fi Verbose Logging

It's possible to increase verbosity of the wpa_supplicant changing the init.*.rc file adding -d option:

service wpa_supplicant /system/bin/wpa_supplicant \
   -d -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
   -I/system/etc/wifi/wpa_supplicant_overlay.conf -O/data/misc/wifi/sockets \
   -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0

4. References[edit source]