Our application attempts to solve a critical humanitarian problem but is--admittedly unusual but for very good reasons--highly dependent on how quickly a phone associates with our WiFi access point. This is true even and especially if the user hasn't touched their phone in a while and maybe we come in range of them briefly. Much of this happens outside of cellular range.
Seconds matter, and yet despite our best efforts to read platform documentation and other publicly available information, we're sometimes seeing minutes and sometimes close to an hour before a phone connects to an access point it has continuous and perfectly strong reception of. On both platforms, our app has preconfigured an SSID for this purpose, however performance with user-created SSIDs is interesting too.
Let's take Android as an example, as it's more transparent and app-friendly in its philosophy (e.g. stated concern for if the "core function of the app is adversely affected" by battery optimization). In an extreme experiment to determine minimum response time, a phone is configured with:
- WiFi during sleep = always
- WiFi lock held by application
- Partial wake lock held by application
- Exemption from battery optimization for the application
- New SSID each time, in case OS "learns" that SSID doesn't have internet connectivity
- Beacon rate set from 10 Hz to 30 Hz (found to improve sometimes) In this configuration, we're still not getting completely consistent results. We think perhaps the difference between application and device, or maintaining an association vs. establishing one, might be the underlying reasons.
So the questions are:
- Does anyone know other ideas or variables to test? (evidence for them is critical vs. random guesses that explode the test matrix)
- Other people who've worked on this problem?
- Documentation/blogs/etc. we might have missed?
- People, especially within Apple or Google, who might be willing to help?
We're even willing to buy coffee or dinner, travel, pay consulting rates in order to support people with the right expertise.
UPDATE: So it's pretty clear that even though passively listening for AP beacons is possible, reasonable, and expected, Android isn't listening for WiFi beacons unless it's actively scanning. In other words, to maximize association responsiveness, you have to put WifiManager.startScan() in a tight (15 Hz) loop.
So... to do that, you have to have code running all the time, which actually turns out to be easy by starting a new scan from your SCAN_RESULTS_AVAILABLE_ACTION intent receiver. This code will in fact keep running during doze (IDLE state), which is great! (effect on battery life TBD, but obviously non-zero)
The problem now is that the WiFi radio is shutting off in that mode, even though WifiManager.isWifiEnabled() still reports true. Scans simply return in 20 ms instead of 4000. I'm thinking to see if any remotely WiFi-related APIs will trigger it to wake up, like P2P, WPS, or Hotspot2.
SECOND UPDATE: P2P and WPS had no effect. But scans returning in 20 ms were still actually scanning--you can see the ScanResults changing! How often, however, depended on the Doze mode, it seems. Under full IDLE, it happened every ~130 sec, while IDLE_MAINTENANCE it still happened continuously, like it does in ACTIVE and INACTIVE states. That's still not scanning 90% of the time, however.