流程框架图
通常我们在设备开启wifi之后,等会会自动扫描出周围的热点。
下面看下自动扫描周围热点的流程
代码流程
1. ClientModeManager.ClientModeStateMachine
- ClientModeStateMachine 由CMD_START 转换到StartedState
- StartedState 状态机,在更新wifiState时,发送广播 WifiManager.WIFI_STATE_CHANGED_ACTION , 通知WifiTracker 开始进行Scan
frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeManager.java
public boolean processMessage(Message message) {.... mClientInterfaceName = mWifiNative.setupInterfaceForClientMode....transitionTo(mStartedState); //跳转到 StartedState
}private class StartedState extends State {...private void onUpChanged(boolean isUp) {.... sendScanAvailableBroadcast(true);mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE,// 发 WifiManager.WIFI_STATE_CHANGED_ACTION 广播通知 wifiTracker 启动startScanupdateWifiState(WifiManager.WIFI_STATE_ENABLED,WifiManager.WIFI_STATE_ENABLING); }
}
2. WifiTracker.BroadcastReceiver --> wifiManager.StartScan
- WifiTracker 广播监听到WifiManager.WIFI_STATE_CHANGED_ACTION ,开启wifiManager.StartScan
frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
public void onReceive(Context context, Intent intent) {if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)){updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,WifiManager.WIFI_STATE_UNKNOWN));
}
}
private void updateWifiState(int state) {1. WifiManager.WIFI_STATE_ENABLEDmScanner.resume();2.wifi 非enabled 则 mScanner.pause();
}
public void handleMessage(Message message) {.. mWifiManager.startScan(); // 开启Wifi Scan
}
3. wifiManager.StartScan --> WifiServiceImpl --> ScanRequestProxy.StartScan
- 获取mWifiScanner 实例
- 检查 调用者UID , apk package 是否有权限进行Scan,如无则直接放回
- Create a worksource using the caller’s UID.
- Create the scan settings.
- 初始化Scan 的band 为DFS,是否Scan 隐藏的AP
- mWifiScanner 发起StartScan
frameworks/opt/net/wifi/service/java/com/android/server/wifi/ScanRequestProxy.java
public boolean startScan(int callingUid, String packageName){retrieveWifiScannerIfNecessary();...// Create a worksource using the caller's UID.WorkSource workSource = new WorkSource(callingUid);// Create the scan settings.WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings();// always do full scanssettings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN| WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;mWifiScanner.startScan(settings, new ScanRequestProxyScanListener(), workSource);
}
4. WifiScanner.startScan --> WifiScaningServiceImpl.ClientHandler.handleMessage
- 发送scan 请求[CMD_START_SINGLE_SCAN ] to WifiScaningServiceImpl 处理
frameworks/base/wifi/java/android/net/wifi/WifiScanner.java
public void startScan(ScanSettings settings, ScanListener listener, WorkSource workSource) {scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
}
5. WifiScanner.startScan --> WifiScaningServiceImpl.ClientHandler.handleMessage
- 先进行有效Scan检查
- 当前正在Scanning,如为有效的(活)scaning,标志为ActiveScans,否则标志为PendingScans
- 当前非Scanning,标志为PendingScans,开启一次新的Scan – tryToStartNewScan()
- 非有效Scan,上报错误Failed
frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.javaclass DriverStartedState extends State {case WifiScanner.CMD_START_SINGLE_SCAN:.... 一大堆code (其实就干了几件事情,见上面描述)....tryToStartNewScan();}
6. WifiScaningServiceImpl.tryToStartNewScan – WifiNative.scan
- WifiScaningServiceImpl 到WifiScannerImpl
- WifiScannerImpl 再到WificondScannerImpl
- WificondScannerImpl最终到WifiNative , 可见与Android N 相比,O、P 的Scan变化太大,但是其套路还是不变,就是上面的环节无论是如何地进行封装,最后还是给到WifiNative 来处理
frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
void tryToStartNewScan() {....mScannerImpl.startSingleScan(settings, this);
}frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WifiScannerImpl.java
public abstract boolean startSingleScan(WifiNative.ScanSettings settings,WifiNative.ScanEventHandler eventHandler);frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WificondScannerImpl.javapublic boolean startSingleScan(WifiNative.ScanSettings settings, WifiNative.ScanEventHandler eventHandler) {....freqs = allFreqs.getScanFreqs();success = mWifiNative.scan(mIfaceName, settings.scanType, freqs, hiddenNetworkSSIDSet);}
7. WifiNative.scan --> WificondControl
- WifiNative 转到 WificondControl
- WificondControl 通过binder 到wificond
- wificond 开始初步的scan 任务 (scannerImpl.scan)
- scannerImpl 传到scan_utils
- scan_utils 通过netlink 将 NL80211_CMD_TRIGGER_SCAN传递wpa_supplicant(driver_nl80211_event.c)
- driver_nl80211_event 将cmd下到wlan drv 里,开始了真正的干活 – scanning
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
public boolean scan( @NonNull String ifaceName, int scanType, Set<Integer> freqs, Set<String> hiddenNetworkSSIDs) {
mWificondControl.scan(ifaceName, scanType, freqs, hiddenNetworkSSIDs);
}frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.javapublic boolean scan(@NonNull String ifaceName, int scanType, Set<Integer> freqs,Set<String> hiddenNetworkSSIDs)
{.. scannerImpl.scan(settings);
}system/connectivity/wificond/scanning/scanner_impl.cpp
Status ScannerImpl::scan(const SingleScanSettings& scan_settings, bool* out_success) {scan_utils_->Scan(interface_index_, request_random_mac, scan_type,ssids, freqs, &error_code); //
}
system/connectivity/wificond/scanning/scan_utils.cpp
bool ScanUtils::Scan(uint32_t interface_index,bool request_random_mac,int scan_type,const vector<vector<uint8_t>>& ssids,const vector<uint32_t>& freqs,int* error_code) {NL80211Packet trigger_scan(netlink_manager_->GetFamilyId(),NL80211_CMD_TRIGGER_SCAN,netlink_manager_->GetSequenceNumber(),getpid());if (scan_flags) {trigger_scan.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_SCAN_FLAGS,scan_flags));}// We are receiving an ERROR/ACK message instead of the actual// scan results here, so it is OK to expect a timely response because// kernel is supposed to send the ERROR/ACK back before the scan starts.vector<unique_ptr<const NL80211Packet>> response;if (!netlink_manager_->SendMessageAndGetAckOrError(trigger_scan,error_code)) {// Logging is done inside |SendMessageAndGetAckOrError|.return false;}
}
8. 扫描结果回传
- 具体与scan 执行流恰为逆向,可参见上面的整体框架图
- 这里简单说明下,当wlan drv 完成scan 之后
- 由 wificond 直接给到WificondControl,
- WificondControl.OnScanResultReady 上报 WifiMonitor
- WifiMonitor -> WificondScannerImpl -> WifiScaningServiceImpl->
- WifiScaningServiceImpl ->WifiService --> WifiTraker --> WifiSettings 刷新扫描结果