文章目录

    • 流程框架图
    • 代码流程
      • 1. ClientModeManager.ClientModeStateMachine
      • 2. WifiTracker.BroadcastReceiver --> wifiManager.StartScan
      • 3. wifiManager.StartScan --> WifiServiceImpl --> ScanRequestProxy.StartScan
      • 4. WifiScanner.startScan --> WifiScaningServiceImpl.ClientHandler.handleMessage
      • 5. WifiScanner.startScan --> WifiScaningServiceImpl.ClientHandler.handleMessage
      • 6. WifiScaningServiceImpl.tryToStartNewScan -- WifiNative.scan
      • 7. WifiNative.scan --> WificondControl
      • 8. 扫描结果回传

流程框架图

通常,我们在设备开启Wifi之后,等会儿自动扫描出周围的热点,注意此时我们并没有点击扫描键,只是点击了一下wifi 开关就可以完成两件事情(1. 开启wifi,2. 扫描周围热点),问题,第二点是如何实现的呢?请详看本文 ~~ 
  • 这里先参考Android P Wifi Enable 流程
  • 有上一步,本文就容易理解
  • 先上一张流程图

代码流程

以下的代码流程,在Android P WiFi Enable 流程基础上往下继续

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.javapublic 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 启动startScan     updateWifiState(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.javapublic 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.javapublic 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 scans        settings.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.javapublic 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.java class 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.javavoid tryToStartNewScan() {....mScannerImpl.startSingleScan(settings, this);}frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WifiScannerImpl.javapublic abstract boolean startSingleScan(WifiNative.ScanSettings settings,WifiNative.ScanEventHandler eventHandler);frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java public 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.javapublic boolean scan( @NonNull String ifaceName, int scanType, Set freqs, Set hiddenNetworkSSIDs) {mWificondControl.scan(ifaceName, scanType, freqs, hiddenNetworkSSIDs);}frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java  public boolean scan(@NonNull String ifaceName, int scanType, Set freqs,Set hiddenNetworkSSIDs){   ..     scannerImpl.scan(settings); }system/connectivity/wificond/scanning/scanner_impl.cppStatus 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.cppbool ScanUtils::Scan(uint32_t interface_index,                     bool request_random_mac,                     int scan_type,                     const vector>& ssids,                     const vector& 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(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> 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 刷新扫描结果

更多相关文章

  1. Android控制闪光灯的方法(打开与关闭)
  2. Android(安卓)音效提示与振动提示
  3. Android(安卓)input输入设备键值从底层到应用层的映射流程
  4. Android控制闪光灯的方法(打开与关闭)
  5. 列出Android设备中所有启动的服务,及判断某个服务是否开启
  6. android launcher 启动流程
  7. Android(安卓)蓝牙开发基本流程
  8. Android(安卓)应用进程启动流程
  9. Android(安卓)apk打包流程,AAPT打包,apk瘦身

随机推荐

  1. android webview 文字复制
  2. Android:获取网页源代码
  3. Android(安卓)震动示例--心跳效果
  4. Failed to resolve: com.android.support
  5. Android(安卓)中文字符转UTF-8编码
  6. Android(安卓)GridView
  7. android添加联系人(直接添加到联系人数据
  8. Android下拉刷新上拉加载控件的使用
  9. android中socket编程
  10. android设置多个类似APP其中的一个为默认