Saturday, March 21, 2015

Looking under the hood of WiFi scans

In this post, I would like to bring some light into WiFi network scans on Android. It's always good to know, what you are dealing with, plus this knowledge can be used to create effective implementation of applications using WiFi scans, such as WiFi beacon.

First, let me introduce the general approach in gathering info about surrounding WiFi networks. And then, we will look into more Android specific stuff. So what kind of scans do we have?

Active scan

A device needs to tune in its radio to particular channel and then it transmits probe request. After this it waits about 40 millis for probe responses from APs on that channel. Device repeats this process over all accessible channels. This procedure is faster comparing to passive scan, but it also consumes more energy, since the radio also transmits frames, not only receives them.

Passive scan

Passive scans are slower to perform, because the device needs to listen on every channel for some period of time, waiting for broadcast beacons. Beacon frames are transmitted by APs periodically to announce the presence of a wireless LAN. Beacon frames contain all the information about its network. This approach consumes less energy, since the radio doesn't use transceiver, but only the receiver. It also takes more time to finish, since it has to listen on every channel.

Compared to Bluetooth Low Energy (BLE), 2.4 GHz WiFi must scan up to 11-14 channels (depending on country) spaced 5 MHz apart, BLE scans just 3 channels with 2 MHz spacing. But important thing to take into account is the actual use of BLE, which is additional, comparing to WiFi, which beginning with Android 4.3 is in on by default. Jelly bean and newer use “Scanning always available” mode to improve location service, even though your WiFi adapter is turned off.

In my previous post - WiFi Beacon - I use a background service to perform regular WiFi scans. Since the system saves power by turning off unnecessary services, I use the WIFI_MODE_SCAN_ONLY wake lock. As its name is self-explanatory, it allows only performing WiFi scans on explicit request. Without wake lock the testing device (Asus Nexus 7 API 22) goes to sleep approximately after 1 minute after screen-off event.

Android and WiFi scans

According to my research, Android powered devices generally use passive scans for gathering info about surrounding networks.  If we study the source codes of, we can find hidden method startScanActive().

“Request a scan for access points. Returns immediately. The availability of the results is made known later by means of an asynchronous event sent on completion of the scan. This is a variant of startScan that forces an active scan, even if passive scans are the current default.”

This method was present in the API up to Android version 4.2. My guess is that this method was used internally by the system to perform quick network scans in the earlier versions of Android. According to my tests, even though this method can be accessed via reflection API, the gathered results (comparing to standard startScan()) yield the same results as for the time of result delivery.

So now we know that Android uses passive scanning. But we also know that this approach may be time consuming. But how much consuming that is? And most importantly, is that duration universal for all devices?

As you can see, the interval between successive scans varies significantly. Some devices are faster in scanning than others. Android not always receives AP beacon, while listening at selected frequency. Therefore it cheats a little bit, and even if no APs were discovered, it provides you old results. Following test simulates for how long we can get AP in scan results, even though it has been shut down. Similar approach is used in BLE scanning. Since iBeacons usually advertise frequently (approximately once in 500ms), majority of received signals are duplicates, some devices process only 25 to 33% of all signals, saving battery life.

Beacon interval of AP plays also its role, but it seems not very significant. Notice the only change on the Samsung device.

And this is basically it. One last thing, look out for timestamps. As of API 17, every scan has its timestamp, so you can eventually omit the duplicate ones.


Post a Comment