Android P WiFi扫描流程详解

源码链接
从WiFi成功开启以后开始梳理:

1、ClientModeManager

  • ClientModeStateMachine 由CMD_START 转换到StartedState
  • StartedState 状态机,在更新wifiState时,发送广播 WifiManager.WIFI_STATE_CHANGED_ACTION , 通知WifiTracker 开始进行Scan
private class StartedState extends State {

         if (isUp) {
             Log.d(TAG, "Wifi is ready to use for client mode");
             sendScanAvailableBroadcast(true);
             mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE,
                                                  mClientInterfaceName);
             updateWifiState(WifiManager.WIFI_STATE_ENABLED,
                             WifiManager.WIFI_STATE_ENABLING);
         .............
     }

2、WifiTracker–>WifiManager
WifiTracker 广播监听到WifiManager.WIFI_STATE_CHANGED_ACTION ,执行updateWifiState,确认WIFi开启以后,执行Scanner的resume函数。开启wifiManager.StartScan

final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
            updateWifiState(
                    intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                            WifiManager.WIFI_STATE_UNKNOWN));
private void updateWifiState(int state) {
    if (state == WifiManager.WIFI_STATE_ENABLED) {
        if (mScanner != null) {
            // We only need to resume if mScanner isn't null because
            // that means we want to be scanning.
            mScanner.resume();
        }

resume函数会发送MSG_SCAN消息,MSG_SCAN消息的处理结果就是调用wifiManager.StartScan。

class Scanner extends Handler {
    static final int MSG_SCAN = 0;

    private int mRetry = 0;

    void resume() {
        if (!hasMessages(MSG_SCAN)) {
            sendEmptyMessage(MSG_SCAN);
        }
    }
public void handleMessage(Message message) {
    if (message.what != MSG_SCAN) return;
    if (mWifiManager.startScan()) {
        mRetry = 0;

3、WifiManager–>WifiServiceImpl

@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
public boolean startScan(WorkSource workSource) {
    try {
        String packageName = mContext.getOpPackageName();
        return mService.startScan(packageName);
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

4、WifiServiceImpl–>ScanRequestProxy

public boolean startScan(String packageName) {
    try {
        mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, callingUid);
        Mutable<Boolean> scanSuccess = new Mutable<>();
        boolean runWithScissorsSuccess = mWifiInjector.getWifiStateMachineHandler()
                .runWithScissors(() -> {
                    scanSuccess.value = mScanRequestProxy.startScan(callingUid, packageName);
                }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
    return true;
}

5、ScanRequestProxy–>WifiScanner
先获取扫描的设置,然后再开始扫描。

    public boolean startScan(int callingUid, String packageName) {
        // Create the scan settings.
        WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings();
        // Scan requests from apps with network settings will be of high accuracy type.
        if (fromSettingsOrSetupWizard) {
            settings.type = WifiScanner.TYPE_HIGH_ACCURACY;
        }
        // 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;
        if (mScanningForHiddenNetworksEnabled) {
            // retrieve the list of hidden network SSIDs to scan for, if enabled.
            List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList =
                    mWifiConfigManager.retrieveHiddenNetworkList();
            settings.hiddenNetworks = hiddenNetworkList.toArray(
                    new WifiScanner.ScanSettings.HiddenNetwork[hiddenNetworkList.size()]);
        }
        mWifiScanner.startScan(settings, new ScanRequestProxyScanListener(), workSource);
        mIsScanProcessingComplete = false;
        return true;
    }

6、WifiScanner.–>WifiScanningServiceImpl
发送scan请求CMD_START_SINGLE_SCAN。

public void startScan(ScanSettings settings, ScanListener listener, WorkSource workSource) {
     Preconditions.checkNotNull(listener, "listener cannot be null");
     int key = addListener(listener);
     if (key == INVALID_KEY) return;
     validateChannel();
     Bundle scanParams = new Bundle();
     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);
 }

7、WifiScanningServiceImpl–>WifiScannerIm0l
先进行有效Scan检查
当前正在Scanning,如为有效的(活)scaning,标志为ActiveScans,否则标志为PendingScans
当前非Scanning,标志为PendingScans,开启一次新的Scan – tryToStartNewScan()
非有效Scan,上报错误Failed

        class DriverStartedState extends State {
            @Override
            public boolean processMessage(Message msg) {

                switch (msg.what) {
                    case CMD_DRIVER_LOADED:
                        // Ignore if we're already in driver loaded state.
                        return HANDLED;
                    case WifiScanner.CMD_START_SINGLE_SCAN:
                   ..............
                            } else {
                                mPendingScans.addRequest(ci, handler, workSource, scanSettings);
                                tryToStartNewScan();
                            }
                       
            }
        }
        void tryToStartNewScan() {
            .............
            if (mScannerImpl.startSingleScan(settings, this)) {
                mPendingScans.clear();
                transitionTo(mScanningState);
            } else {
                mWifiMetrics.incrementScanReturnEntry(
                        WifiMetricsProto.WifiLog.SCAN_UNKNOWN, mPendingScans.size());
                // notify and cancel failed scans
                sendOpFailedToAllAndClear(mPendingScans, WifiScanner.REASON_UNSPECIFIED,
                        "Failed to start single scan");
            }
        }

8、WifiScannerImpl–>WificondScannerImpl

public abstract boolean startSingleScan(WifiNative.ScanSettings settings,
        WifiNative.ScanEventHandler eventHandler);

9、WificondScannerImpl–>WifiNative

public boolean startSingleScan(WifiNative.ScanSettings settings,
        WifiNative.ScanEventHandler eventHandler) {
        if (!allFreqs.isEmpty()) {
            freqs = allFreqs.getScanFreqs();
            success = mWifiNative.scan(
                    mIfaceName, settings.scanType, freqs, hiddenNetworkSSIDSet);
            if (!success) {
                Log.e(TAG, "Failed to start scan, freqs=" + freqs);
            }

        return true;
    }
}

10、WifiNative–>WificondControl

public boolean scan(
        @NonNull String ifaceName, int scanType, Set<Integer> freqs,
        Set<String> hiddenNetworkSSIDs) {
    return mWificondControl.scan(ifaceName, scanType, freqs, hiddenNetworkSSIDs);
}

11、WificondControl–>scanner_impl.cpp

    public boolean scan(@NonNull String ifaceName,
                        int scanType,
                        Set<Integer> freqs,
                        Set<String> hiddenNetworkSSIDs) {
        ............
        try {
            return scannerImpl.scan(settings);
        } catch (RemoteException e1) {
            Log.e(TAG, "Failed to request scan due to remote exception");
        }
        return false;
    }

12、scanner_impl.cpp–>scan_utils.cpp

Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
                         bool* out_success) {
  ................
  int error_code = 0;
  if (!scan_utils_->Scan(interface_index_, request_random_mac, scan_type,
                         ssids, freqs, &error_code)) {
    CHECK(error_code != ENODEV) << "Driver is in a bad state, restarting wificond";
    *out_success = false;
    return Status::ok();
  }
}

13、scan_utils.cpp
scan_utils 通过netlink 将 NL80211_CMD_TRIGGER_SCAN传递wpa_supplicant(driver_nl80211_event.c)

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());
  trigger_scan.AddFlag(NLM_F_ACK);
  NL80211Attr<uint32_t> if_index_attr(NL80211_ATTR_IFINDEX, interface_index);

  NL80211NestedAttr ssids_attr(NL80211_ATTR_SCAN_SSIDS);
  for (size_t i = 0; i < ssids.size(); i++) {
    ssids_attr.AddAttribute(NL80211Attr<vector<uint8_t>>(i, ssids[i]));
  }
  NL80211NestedAttr freqs_attr(NL80211_ATTR_SCAN_FREQUENCIES);
  for (size_t i = 0; i < freqs.size(); i++) {
    freqs_attr.AddAttribute(NL80211Attr<uint32_t>(i, freqs[i]));
  }

  trigger_scan.AddAttribute(if_index_attr);
  trigger_scan.AddAttribute(ssids_attr);
  // An absence of NL80211_ATTR_SCAN_FREQUENCIES attribue informs kernel to
  // scan all supported frequencies.
  if (!freqs.empty()) {
    trigger_scan.AddAttribute(freqs_attr);
  }

  uint32_t scan_flags = 0;
  if (request_random_mac) {
    scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
  }
  switch (scan_type) {
    case IWifiScannerImpl::SCAN_TYPE_LOW_SPAN:
      scan_flags |= NL80211_SCAN_FLAG_LOW_SPAN;
      break;
    case IWifiScannerImpl::SCAN_TYPE_LOW_POWER:
      scan_flags |= NL80211_SCAN_FLAG_LOW_POWER;
      break;
    case IWifiScannerImpl::SCAN_TYPE_HIGH_ACCURACY:
      scan_flags |= NL80211_SCAN_FLAG_HIGH_ACCURACY;
      break;
    case IWifiScannerImpl::SCAN_TYPE_DEFAULT:
      break;
    default:
      CHECK(0) << "Invalid scan type received: " << scan_type;
  }
  if (scan_flags) {
    trigger_scan.AddAttribute(
        NL80211Attr<uint32_t>(NL80211_ATTR_SCAN_FLAGS,
                              scan_flags));
  }

  vector<unique_ptr<const NL80211Packet>> response;
  if (!netlink_manager_->SendMessageAndGetAckOrError(trigger_scan,
                                                     error_code)) {
    // Logging is done inside |SendMessageAndGetAckOrError|.
    return false;
  }
  return true;
}

14、扫描结果回传
WificondControl.OnScanResultReady 上报 WifiMonitor
WifiMonitor -> WificondScannerImpl -> WifiScaningServiceImpl->
WifiScaningServiceImpl ->WifiService --> WifiTracker --> WifiSettings 刷新扫描结果

关注公众号,获取更多开发必备知识
在这里插入图片描述

你可能感兴趣的:(WIfi,Android)