Android 11 WiFi扫描流程

ActiveModeWarden中注册了ClientListener监听器。我们接着这个逻辑继续梳理一下打开WiFi以后的扫描流程。

一、WiFi打开以后,ClientListener会监听到,这时候会更新扫描状态。 frameworks/opt/net/wifi/service/java/com/android/server/wifi/ActiveModeWarden.java

private class ClientListener extends ModeCallback implements ActiveModeManager.Listener {
     @Override
     public void onStarted() {
         updateClientScanMode();
         updateBatteryStats();
     }

复制

在这里enable扫描

private void updateClientScanMode() {
    boolean scanEnabled = hasAnyClientModeManager();
    boolean scanningForHiddenNetworksEnabled;

    if (mContext.getResources().getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) {
        scanningForHiddenNetworksEnabled = hasAnyClientModeManager();
    } else {
        scanningForHiddenNetworksEnabled = hasAnyClientModeManagerInConnectivityRole();
    }
    mScanRequestProxy.enableScanning(scanEnabled, scanningForHiddenNetworksEnabled);
}

复制

二、在这里调用WifiScanner并且发送扫描广播 frameworks/opt/net/wifi/service/java/com/android/server/wifi/ScanRequestProxy.java

public void enableScanning(boolean enable, boolean enableScanningForHiddenNetworks) {
    if (enable) {
        enableScanningInternal(true);
        mScanningForHiddenNetworksEnabled = enableScanningForHiddenNetworks;
        Log.i(TAG, "Scanning for hidden networks is "
                + (enableScanningForHiddenNetworks ? "enabled" : "disabled"));
    } else {
        enableScanningInternal(false);
    }
    mScanningEnabled = enable;
}

复制

private void enableScanningInternal(boolean enable) {
     if (!retrieveWifiScannerIfNecessary()) {
         Log.e(TAG, "Failed to retrieve wifiscanner");
         return;
     }
     mWifiScanner.setScanningEnabled(enable);
     sendScanAvailableBroadcast(mContext, enable);
     clearScanResults();
     Log.i(TAG, "Scanning is " + (enable ? "enabled" : "disabled"));
 }

复制

private void sendScanAvailableBroadcast(Context context, boolean available) {
    Log.d(TAG, "Sending scan available broadcast: " + available);
    final Intent intent = new Intent(WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED);
    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, available);
    context.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}

复制

三、这里发送了CMD_ENABLE 消息,我们看这个消息的处理。 frameworks/base/wifi/java/android/net/wifi/WifiScanner.java

public void setScanningEnabled(boolean enable) {
    validateChannel();
    mAsyncChannel.sendMessage(enable ? CMD_ENABLE : CMD_DISABLE);
}

复制

四、在这里启动scan,创建了WifiScannerImplFactory frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java

switch (msg.what) {
   case WifiScanner.CMD_ENABLE:
       Log.i(TAG, "Received a request to enable scanning, UID = " + msg.sendingUid);
       setupScannerImpls();
       mBackgroundScanStateMachine.sendMessage(Message.obtain(msg));
       mSingleScanStateMachine.sendMessage(Message.obtain(msg));
       mPnoScanStateMachine.sendMessage(Message.obtain(msg));
       break;

复制

private void setupScannerImpls() {
    Set<String> ifaceNames = mWifiNative.getClientInterfaceNames();
    if (ArrayUtils.isEmpty(ifaceNames)) {
        loge("Failed to retrieve client interface names");
        return;
    }
    Set<String> ifaceNamesOfImplsAlreadySetup = mScannerImpls.keySet();
    if (ifaceNames.equals(ifaceNamesOfImplsAlreadySetup)) {
        // Scanner Impls already exist for all ifaces (back to back CMD_ENABLE sent?).
        Log.i(TAG, "scanner impls already exists");
        return;
    }
    // set of impls to teardown.
    Set<String> ifaceNamesOfImplsToTeardown = new ArraySet<>(ifaceNamesOfImplsAlreadySetup);
    ifaceNamesOfImplsToTeardown.removeAll(ifaceNames);
    // set of impls to be considered for setup.
    Set<String> ifaceNamesOfImplsToSetup = new ArraySet<>(ifaceNames);
    ifaceNamesOfImplsToSetup.removeAll(ifaceNamesOfImplsAlreadySetup);

    for (String ifaceName : ifaceNamesOfImplsToTeardown) {
        WifiScannerImpl impl = mScannerImpls.remove(ifaceName);
        if (impl == null) continue; // should never happen
        impl.cleanup();
        Log.i(TAG, "Removed an impl for " + ifaceName);
    }
    for (String ifaceName : ifaceNamesOfImplsToSetup) {
        WifiScannerImpl impl = mScannerImplFactory.create(mContext, mLooper, mClock, ifaceName);
        if (impl == null) {
            loge("Failed to create scanner impl for " + ifaceName);
            continue;
        }
        // If this new scanner impl does not offer any new bands to scan, then we should
        // ignore it.
        if (!doesAnyExistingImplSatisfy(impl)) {
            mScannerImpls.put(ifaceName, impl);
            Log.i(TAG, "Created a new impl for " + ifaceName);
        } else {
            Log.i(TAG, "All the channels on the new impl for iface " + ifaceName
                    + " are already satisfied by an existing impl. Skipping..");
            impl.cleanup(); // cleanup the impl before discarding.
        }
    }
}

复制

五、启动Scan以后,这时候就要开始扫描了。开始扫描的逻辑是从Settings触发的。 WifiTracker接收到wifi状态改变的广播以后, packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java

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

        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
            updateWifiState(
                    intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                            WifiManager.WIFI_STATE_UNKNOWN));

复制

如果wifi是启动的,则刷新scanner

private void updateWifiState(int state) {
    if (isVerboseLoggingEnabled()) {
        Log.d(TAG, "updateWifiState: " + state);
    }
    if (state == WifiManager.WIFI_STATE_ENABLED) {
        synchronized (mLock) {
            if (mScanner != null) {
                // We only need to resume if mScanner isn't null because
                // that means we want to be scanning.
                mScanner.resume();
            }
        }
    } 
    mListener.onWifiStateChanged(state);
}

复制

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

    private int mRetry = 0;

    void resume() {
        if (isVerboseLoggingEnabled()) {
            Log.d(TAG, "Scanner resume");
        }
        if (!hasMessages(MSG_SCAN)) {
            sendEmptyMessage(MSG_SCAN);
        }
    }

复制

这里接收到MSG_SCAN消息以后调用了wifimanager的startScan

public void handleMessage(Message message) {
    if (message.what != MSG_SCAN) return;
    if (mWifiManager.startScan()) {
        mRetry = 0;
    } else if (++mRetry >= 3) {
        mRetry = 0;
        if (mContext != null) {
            Toast.makeText(mContext, R.string.wifi_fail_to_scan, Toast.LENGTH_LONG).show();
        }
        return;
    }
    sendEmptyMessageDelayed(MSG_SCAN, WIFI_RESCAN_INTERVAL_MS);

复制

六、wifimanager一直调用到ScanRequestProxy,在这里会初始化一些扫描的设置参数,比如扫描信道,隐藏网络等等 wifimanager --> WifiServiceImpl --> ScanRequestProxy --> WifiScanner

    public boolean startScan(int callingUid, String packageName) {
        if (!mScanningEnabled || !retrieveWifiScannerIfNecessary()) {
            Log.e(TAG, "Failed to retrieve wifiscanner");
            sendScanResultFailureBroadcastToPackage(packageName);
            return false;
        }
        boolean fromSettingsOrSetupWizard =
                mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)
                        || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(callingUid);
        // Check and throttle scan request unless,
        // a) App has either NETWORK_SETTINGS or NETWORK_SETUP_WIZARD permission.
        // b) Throttling has been disabled by user.
        if (!fromSettingsOrSetupWizard && mThrottleEnabled
                && shouldScanRequestBeThrottledForApp(callingUid, packageName)) {
            Log.i(TAG, "Scan request from " + packageName + " throttled");
            sendScanResultFailureBroadcastToPackage(packageName);
            return false;
        }
        // Create a worksource using the caller's UID.
        WorkSource workSource = new WorkSource(callingUid, 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.SCAN_TYPE_HIGH_ACCURACY;
        }
        // always do full scans
        settings.band = WifiScanner.WIFI_BAND_ALL;
        settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
        if (mScanningForHiddenNetworksEnabled) {
            settings.hiddenNetworks.clear();
            // retrieve the list of hidden network SSIDs from saved network to scan for, if enabled.
            settings.hiddenNetworks.addAll(mWifiConfigManager.retrieveHiddenNetworkList());
            // retrieve the list of hidden network SSIDs from Network suggestion to scan for.
            settings.hiddenNetworks.addAll(
                    mWifiInjector.getWifiNetworkSuggestionsManager().retrieveHiddenNetworkList());
        }
        mWifiScanner.startScan(settings, new HandlerExecutor(mHandler),
                new ScanRequestProxyScanListener(), workSource);
        return true;
    }

复制

七、 frameworks/base/wifi/java/android/net/wifi/WifiScanner.java

public void startScan(ScanSettings settings, @Nullable @CallbackExecutor Executor executor,
        ScanListener listener, WorkSource workSource) {
    Objects.requireNonNull(listener, "listener cannot be null");
    int key = addListener(listener, executor);
    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);
    scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
    scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getAttributionTag());
    mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
}

复制

可以看到replySucceeded(msg);会返回一个扫描成功的消息。 如果已经在扫描,则把新的扫描请求发送给当前扫描,如果当前没有扫描,则开启新的扫描。 frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java

class DriverStartedState extends State {
    public boolean processMessage(Message msg) {
        ClientInfo ci = mClients.get(msg.replyTo);
        switch (msg.what) {
            case WifiScanner.CMD_START_SINGLE_SCAN:
                Bundle scanParams = (Bundle) msg.obj;
                replySucceeded(msg);
                    if (getCurrentState() == mScanningState) {
                        if (activeScanSatisfies(scanSettings)) {
                            mActiveScans.addRequest(ci, handler, workSource, scanSettings);
                        } else {
                            mPendingScans.addRequest(ci, handler, workSource, scanSettings);
                        }
                    } else {
                        mPendingScans.addRequest(ci, handler, workSource, scanSettings);
                        tryToStartNewScan();
                    }
                }
                return HANDLED;

复制

void tryToStartNewScan() {
    if (mPendingScans.size() == 0) { // no pending requests
        return;
    }
    mChannelHelper.updateChannels();
    // TODO move merging logic to a scheduler
    WifiNative.ScanSettings settings = new WifiNative.ScanSettings();
    settings.num_buckets = 1;
    WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();
    bucketSettings.bucket = 0;
    bucketSettings.period_ms = 0;
    bucketSettings.report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;

    ChannelCollection channels = mChannelHelper.createChannelCollection();
    List<WifiNative.HiddenNetwork> hiddenNetworkList = new ArrayList<>();
    for (RequestInfo<ScanSettings> entry : mPendingScans) {
        settings.scanType = mergeScanTypes(settings.scanType, entry.settings.type);
        channels.addChannels(entry.settings);
        for (ScanSettings.HiddenNetwork srcNetwork : entry.settings.hiddenNetworks) {
            WifiNative.HiddenNetwork hiddenNetwork = new WifiNative.HiddenNetwork();
            hiddenNetwork.ssid = srcNetwork.ssid;
            hiddenNetworkList.add(hiddenNetwork);
        }
        if ((entry.settings.reportEvents & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)
                != 0) {
            bucketSettings.report_events |= WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
        }
    }
    if (hiddenNetworkList.size() > 0) {
        settings.hiddenNetworks = new WifiNative.HiddenNetwork[hiddenNetworkList.size()];
        int numHiddenNetworks = 0;
        for (WifiNative.HiddenNetwork hiddenNetwork : hiddenNetworkList) {
            settings.hiddenNetworks[numHiddenNetworks++] = hiddenNetwork;
        }
    }

    channels.fillBucketSettings(bucketSettings, Integer.MAX_VALUE);

    settings.buckets = new WifiNative.BucketSettings[] {bucketSettings};
    if (mScannerImplsTracker.startSingleScan(settings)) {
        // store the active scan settings
        mActiveScanSettings = settings;
        // swap pending and active scan requests
        RequestList<ScanSettings> tmp = mActiveScans;
        mActiveScans = mPendingScans;
        mPendingScans = tmp;
        // make sure that the pending list is clear
        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");
    }
}

复制

八、ScannerImplsTracker --> WifiScannerImpl --> WifiScannerImplFactory

public static final WifiScannerImplFactory DEFAULT_FACTORY = new WifiScannerImplFactory() {
        public WifiScannerImpl create(Context context, Looper looper, Clock clock,
                @NonNull String ifaceName) {
            WifiNative wifiNative = WifiInjector.getInstance().getWifiNative();
            WifiMonitor wifiMonitor = WifiInjector.getInstance().getWifiMonitor();
            if (TextUtils.isEmpty(ifaceName)) {
                return null;
            }
            if (wifiNative.getBgScanCapabilities(
                    ifaceName, new WifiNative.ScanCapabilities())) {
                return new HalWifiScannerImpl(context, ifaceName, wifiNative, wifiMonitor,
                        looper, clock);
            } else {
                return new WificondScannerImpl(context, ifaceName, wifiNative, wifiMonitor,
                        new WificondChannelHelper(wifiNative), looper, clock);
            }
        }
    };

复制

九、可以看到这俩个代码最后也走到了一起 frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/HalWifiScannerImpl.java frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java

mWificondScannerDelegate =
        new WificondScannerImpl(context, wifiNative, wifiMonitor, mChannelHelper,
                looper, clock);

复制

最后还是调到了WifiNative。逻辑理顺就好了,接下来一定是wifinative去让底层扫描并返回扫描结果

    public boolean startSingleScan(WifiNative.ScanSettings settings,
            WifiNative.ScanEventHandler eventHandler) {
        synchronized (mSettingsLock) {
            for (int i = 0; i < settings.num_buckets; ++i) {
                WifiNative.BucketSettings bucketSettings = settings.buckets[i];
                if ((bucketSettings.report_events
                                & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) {
                    reportFullResults = true;
                }
                allFreqs.addChannels(bucketSettings);
            }
            List<String> hiddenNetworkSSIDSet = new ArrayList<>();
            if (settings.hiddenNetworks != null) {
                int numHiddenNetworks =
                        Math.min(settings.hiddenNetworks.length, MAX_HIDDEN_NETWORK_IDS_PER_SCAN);
                for (int i = 0; i < numHiddenNetworks; i++) {
                    hiddenNetworkSSIDSet.add(settings.hiddenNetworks[i].ssid);
                }
            }
            mLastScanSettings = new LastScanSettings(
                        mClock.getElapsedSinceBootMillis(),
                        reportFullResults, allFreqs, eventHandler);
            Set<Integer> freqs;
            if (!allFreqs.isEmpty()) {
                freqs = allFreqs.getScanFreqs();
                success = mWifiNative.scan(
                        getIfaceName(), settings.scanType, freqs, hiddenNetworkSSIDSet);
            } 
            if (success) {
                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                        mClock.getElapsedSinceBootMillis() + SCAN_TIMEOUT_MS,
                        TIMEOUT_ALARM_TAG, mScanTimeoutListener, mEventHandler);
            } 

            return true;
        }
    }

复制

十、 frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

public boolean scan(
        @NonNull String ifaceName, @WifiAnnotations.ScanType int scanType, Set<Integer> freqs,
        List<String> hiddenNetworkSSIDs) {
    Log.d(TAG, "Scan trigered from WifiNative");
    List<byte[]> hiddenNetworkSsidsArrays = new ArrayList<>();
    for (String hiddenNetworkSsid : hiddenNetworkSSIDs) {
        try {
            byte[] hiddenSsidBytes = WifiGbk.getRandUtfOrGbkBytes(hiddenNetworkSsid);
            if (hiddenSsidBytes.length > WifiGbk.MAX_SSID_LENGTH) {
                Log.e(TAG, "SSID is too long after conversion, skipping this ssid! SSID =" +
                           hiddenNetworkSsid + " , SSID size = " + hiddenSsidBytes.length);
                continue;
            }
            hiddenNetworkSsidsArrays.add(hiddenSsidBytes);
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Illegal argument " + hiddenNetworkSsid, e);
            continue;
        }
    }
    mIfaceNameforPartialScanResult = ifaceName;
    boolean mScanDoneFlag = mWifiCondManager.startScan(ifaceName, scanType, freqs, hiddenNetworkSsidsArrays);
    if (mScanDoneFlag &&
        ((mWifiInjector.getClientModeImpl().isDisconnected()) ||
         mAllowConnectionOnPartialScanResults)) {
          schedulePeriodicPartialScanResult();
    }
    return mScanDoneFlag;
}

复制

这里通过HIDL到了C代码中 frameworks/base/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java

   public boolean startScan(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType,
            @Nullable Set<Integer> freqs, @Nullable List<byte[]> hiddenNetworkSSIDs) {
        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
            return scannerImpl.scan(settings);
        return false;
    }

复制

十一、这里是代码到c++以后的流程,最后把扫描命令发送给了kernel。 system/connectivity/wificond/scanning/scanner_impl.cpp

Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
                         bool* out_success) {
  if (!CheckIsValid()) {
    *out_success = false;
    return Status::ok();
  }

  if (scan_started_) {
    LOG(WARNING) << "Scan already started";
  }
  // Only request MAC address randomization when station is not associated.
  bool request_random_mac =
      wiphy_features_.supports_random_mac_oneshot_scan &&
      !client_interface_->IsAssociated();
  int scan_type = scan_settings.scan_type_;
  if (!IsScanTypeSupported(scan_settings.scan_type_, wiphy_features_)) {
    LOG(DEBUG) << "Ignoring scan type because device does not support it";
    scan_type = SCAN_TYPE_DEFAULT;
  }

  // Initialize it with an empty ssid for a wild card scan.
  vector<vector<uint8_t>> ssids = {
   
   {}};

  vector<vector<uint8_t>> skipped_scan_ssids;
  for (auto& network : scan_settings.hidden_networks_) {
    if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
      skipped_scan_ssids.emplace_back(network.ssid_);
      continue;
    }
    ssids.push_back(network.ssid_);
  }

  LogSsidList(skipped_scan_ssids, "Skip scan ssid for single scan");

  vector<uint32_t> freqs;
  for (auto& channel : scan_settings.channel_settings_) {
    freqs.push_back(channel.frequency_);
  }

  int error_code = 0;
  if (!scan_utils_->Scan(interface_index_, request_random_mac, scan_type,
                         ssids, freqs, &error_code)) {
    if (error_code == ENODEV) {
        nodev_counter_ ++;
        LOG(WARNING) << "Scan failed with error=nodev. counter=" << nodev_counter_;
    }

    if (error_code == ENETDOWN) {
        enetdown_counter_++;
        LOG(WARNING) << "Scan failed with error=iface down. counter=" << enetdown_counter_;
    }
    CHECK((error_code != ENODEV || nodev_counter_ <= 3) &&
          (error_code != ENETDOWN || enetdown_counter_ <= 10))
          << "Driver is in a bad state, restarting wificond";
    *out_success = false;
    return Status::ok();
  }
  nodev_counter_ = 0;
  enetdown_counter_ = 0;
  scan_started_ = true;
  *out_success = true;
  return Status::ok();
}

复制

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 we do not use NLM_F_ACK, we only receive a unicast repsonse
  // when there is an error. If everything is good, scan results notification
  // will only be sent through multicast.
  // If NLM_F_ACK is set, there will always be an unicast repsonse, either an
  // ERROR or an ACK message. The handler will always be called and removed by
  // NetlinkManager.
  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));
  }
  // 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;
  }
  if (*error_code != 0) {
    LOG(ERROR) << "NL80211_CMD_TRIGGER_SCAN failed: " << strerror(*error_code);
    return false;
  }
  return true;
}

复制

system/connectivity/wificond/net/netlink_manager.cpp

bool NetlinkManager::SendMessageAndGetAckOrError(const NL80211Packet& packet,
                                                 int* error_code) {
  unique_ptr<const NL80211Packet> response;
  if (!SendMessageAndGetSingleResponseOrError(packet, &response)) {
    return false;
  }
  uint16_t type = response->GetMessageType();
  if (type != NLMSG_ERROR) {
    LOG(ERROR) << "Receive unexpected message type :" << type;
    return false;
  }

  *error_code = response->GetErrorCode();
  return true;
}

复制

bool NetlinkManager::SendMessageAndGetSingleResponseOrError(
    const NL80211Packet& packet,
    unique_ptr<const NL80211Packet>* response) {
  vector<unique_ptr<const NL80211Packet>> response_vec;
  if (!SendMessageAndGetResponses(packet, &response_vec)) {
    return false;
  }
  if (response_vec.size() != 1) {
    LOG(ERROR) << "Unexpected response size: " << response_vec.size();
    return false;
  }

  *response = std::move(response_vec[0]);
  return true;
}

复制

bool NetlinkManager::SendMessageAndGetResponses(
    const NL80211Packet& packet,
    vector<unique_ptr<const NL80211Packet>>* response) {
  if (!SendMessageInternal(packet, sync_netlink_fd_.get())) {
    return false;
  }
  // Polling netlink socket, waiting for GetFamily reply.
  struct pollfd netlink_output;
  memset(&netlink_output, 0, sizeof(netlink_output));
  netlink_output.fd = sync_netlink_fd_.get();
  netlink_output.events = POLLIN;

  uint32_t sequence = packet.GetMessageSequence();

  int time_remaining = kMaximumNetlinkMessageWaitMilliSeconds;
  // Multipart messages may come with seperated datagrams, ending with a
  // NLMSG_DONE message.
  // ReceivePacketAndRunHandler() will remove the handler after receiving a
  // NLMSG_DONE message.
  message_handlers_[sequence] = std::bind(AppendPacket, response, _1);

  while (time_remaining > 0 &&
      message_handlers_.find(sequence) != message_handlers_.end()) {
    nsecs_t interval = systemTime(SYSTEM_TIME_MONOTONIC);
    int poll_return = poll(&netlink_output,
                           1,
                           time_remaining);

    if (poll_return == 0) {
      LOG(ERROR) << "Failed to poll netlink fd: time out ";
      message_handlers_.erase(sequence);
      return false;
    } else if (poll_return == -1) {
      PLOG(ERROR) << "Failed to poll netlink fd";
      message_handlers_.erase(sequence);
      return false;
    }
    ReceivePacketAndRunHandler(sync_netlink_fd_.get());
    interval = systemTime(SYSTEM_TIME_MONOTONIC) - interval;
    time_remaining -= static_cast<int>(ns2ms(interval));
  }
  if (time_remaining <= 0) {
    LOG(ERROR) << "Timeout waiting for netlink reply messages";
    message_handlers_.erase(sequence);
    return false;
  }
  return true;
}

复制

bool NetlinkManager::SendMessageInternal(const NL80211Packet& packet, int fd) {
  const vector<uint8_t>& data = packet.GetConstData();
  ssize_t bytes_sent =
      TEMP_FAILURE_RETRY(send(fd, data.data(), data.size(), 0));
  if (bytes_sent == -1) {
    PLOG(ERROR) << "Failed to send netlink message";
    return false;
  }
  return true;
}

猜你喜欢

转载自blog.csdn.net/chanimei_11/article/details/124601433