在调试Android P版本下WiFi功能时偶然发现,WiFi模块无法扫描到华为P20手机打开的热点。也即settings界面无法显示出P20手机打开的热点,但是通过如下命令:
iw dev wlan scan | grep SSID
直接向Driver下发扫描命令后,却能获得P20手机的热点信息。怀疑为Driver上报的热点信息在上传路线中被丢弃。跟踪扫描结果的上传路径:
cfg80211_inform_bss
cfg80211_inform_bss_data
cfg80211_bss_update 此函数会将扫描结果保存进内核中
cfg80211_scan_done 此函数通知内核将扫描结果上报
queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk); 内核在work_queue中添加了一个work。
__cfg80211_scan_done scan_done_wk在wiphy_new_nm中初始化为该函数。
nl80211_build_scan_msg
添加事件NL80211_CMD_NEW_SCAN_RESULTS
nl80211_send_scan_msg
nl80211_add_scan_req
nl80211_send_scan_result
从添加的打印结果看,内核中并不涉及相关的过滤,也即在内核中,P20手机的热点信息依然存在。紧接着扫描结果上报到supplicant,相关的打印:
01-01 00:02:44.906 4205 4205 D wpa_supplicant: nl80211: Drv Event 34 (NL80211_CMD_NEW_SCAN_RESULTS) received for wlan0
01-01 00:02:44.906 4205 4205 D wpa_supplicant: wlan0: nl80211: New scan results available
01-01 00:02:44.906 4205 4205 D wpa_supplicant: nl80211: Scan probed for SSID ''
01-01 00:02:44.906 4205 4205 D wpa_supplicant: nl80211: Scan included frequencies: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484 5170 5180 5190 5200 5210 5220 5230 5240 5260 5280 5300 5320 5500 5520 5540 5560 5580 5600 5620 5640 5660 5680 5700 5745 5765 5785 5805 5825 5920 5940 5960 5980 6000 6020 6040
01-01 00:02:44.906 4205 4205 D wpa_supplicant: wlan0: Event SCAN_RESULTS (3) received
01-01 00:02:44.907 4205 4205 D wpa_supplicant: nl80211: Received scan results (26 BSSes)
01-01 00:02:44.907 4205 4205 D wpa_supplicant: wlan0: BSS: Start scan result update 10
从日志中也可以看到,P20热点在supplicant层也正常上报。再网上追溯,注意到存在如下日志:
01-01 00:02:44.913 3585 3668 D WificondScannerImpl: ssid caotimestamp_ms 4498 mLastScanSettings.startTime 159230
01-01 00:02:44.913 3585 3668 D WificondScannerImpl: Filtering out 11 scan results.
可知在WificondScannerImpl模块中存在过滤行为。跟踪其代码,发现过滤处的逻辑为:
if (timestamp_ms > mLastScanSettings.startTime) {
if (mLastScanSettings.singleScanFreqs.containsChannel(
result.frequency)) {
singleScanResults.add(result);
}
} else {
numFilteredScanResults++;
}
至此大致梳理出手机热点无法被扫描到的原因:
1、Framework中记录了一个扫描开始的时间:mClock.getElapsedSinceBootMillis(),该时间为自系统启动以来的毫秒数。
2、在Driver使用函数cfg80211_inform_bss上报扫描结果时,timestamp处填写的是从扫描到的AP的timestamp值,而WificondScannerImpl模块使用了该值与系统时间进行比较。而手机热点开启时,timestamp值从零开始记,导致该值恒定小于系统启动时间,也就在WificondScannerImpl模块被过滤。
修正方法为,在cfg80211_inform_bss上报扫描结果时timestamp值填写为当前获取的系统时间即可。