Android wifi Enable之后扫描流程

流程框架图

通常我们在设备开启wifi之后,等会会自动扫描出周围的热点。

下面看下自动扫描周围热点的流程

代码流程

1. ClientModeManager.ClientModeStateMachine

  • ClientModeStateMachine 由CMD_START 转换到StartedState
  • StartedState 状态机,在更新wifiState时,发送广播 WifiManager.WIFI_STATE_CHANGED_ACTION , 通知WifiTracker 开始进行Scan
java 复制代码
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 启动startScan
     updateWifiState(WifiManager.WIFI_STATE_ENABLED,WifiManager.WIFI_STATE_ENABLING); 
   }
}

2. WifiTracker.BroadcastReceiver --> wifiManager.StartScan

  • WifiTracker 广播监听到WifiManager.WIFI_STATE_CHANGED_ACTION ,开启wifiManager.StartScan
java 复制代码
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_ENABLED
		mScanner.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
java 复制代码
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 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 处理
java 复制代码
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
java 复制代码
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 来处理
java 复制代码
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.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
java 复制代码
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.java
  public 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 刷新扫描结果
相关推荐
Devil枫2 小时前
Kotlin高级特性深度解析
android·开发语言·kotlin
ChinaDragonDreamer2 小时前
Kotlin:2.1.20 的新特性
android·开发语言·kotlin
雨白12 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹14 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空16 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭16 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日17 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安17 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑17 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟21 小时前
CTF Web的数组巧用
android