android wifi scan and auto re-connect

14 篇文章 1 订阅

Target platform: android Q10 platform

android 会将已连接的wifi AP保存到这个文件: data/misc/wifi/WifiConfigStore.xml

然后当wifi 再次打开的时候 scan results后 会将scan results和保存的已连接的wifi AP 中对比, 如果有已保存的wifi网络,则自动重连。

以下是一个已保存的网络节点

ID: 0 SSID: "Pixel_8287" PROVIDER-NAME: null BSSID: null FQDN: null PRIO: 0 HIDDEN: false PMF: false
 NetworkSelectionStatus NETWORK_SELECTION_ENABLED
 hasEverConnected: true
 numAssociation 3
 update time=04-13 15:58:20.958
 creation time=04-13 15:56:48.640
 validatedInternetAccess trusted
 macRandomizationSetting: 0
 mRandomizedMacAddress: 4e:c2:34:a4:04:79
 KeyMgmt: WPA_PSK Protocols: WPA RSN
 AuthAlgorithms: OPEN
 PairwiseCiphers: TKIP CCMP
 GroupCiphers: WEP40 WEP104 TKIP CCMP
 GroupMgmtCiphers:
 SuiteBCiphers:
 PSK/SAE: *
Enterprise config:
IP config:
IP assignment: DHCP
Proxy settings: NONE
 cuid=1000 cname=android.uid.system:1000 luid=1000 lname=android.uid.system:1000 lcuid=1000 userApproved=USER_UNSPECIFIED noInternetAccessExpected=true
lastConnected: 04-13 18:04:49.865
recentFailure: Association Rejection code: 0

 

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiConnectivityManager.java

handleScanResults

    WifiConfiguration candidate = mNetworkSelector.selectNetwork(scanDetails, buildBssidBlacklist(), mWifiInfo, mStateMachine.isConnected(), mStateMachine.isDisconnected(), mUntrustedConnectionAllowed);

 

685    /**
686     * Select the best network from the ones in range.
687     *
688     * @param scanDetails    List of ScanDetail for all the APs in range
689     * @param bssidBlacklist Blacklisted BSSIDs
690     * @param wifiInfo       Currently connected network
691     * @param connected      True if the device is connected
692     * @param disconnected   True if the device is disconnected
693     * @param untrustedNetworkAllowed True if untrusted networks are allowed for connection
694     * @return Configuration of the selected network, or Null if nothing
695     */
696    @Nullable
697    public WifiConfiguration selectNetwork(List<ScanDetail> scanDetails,
698            HashSet<String> bssidBlacklist, WifiInfo wifiInfo,
699            boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) {
700        mFilteredNetworks.clear();
701        mConnectableNetworks.clear();
702        if (scanDetails.size() == 0) {
703            localLog("Empty connectivity scan result");
704            return null;
705        }
706
707        WifiConfiguration currentNetwork =
708                mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());
709
710        // Always get the current BSSID from WifiInfo in case that firmware initiated
711        // roaming happened.
712        String currentBssid = wifiInfo.getBSSID();
713
714        // Shall we start network selection at all?
715        if (!isNetworkSelectionNeeded(scanDetails, wifiInfo, connected, disconnected)) {
716            return null;
717        }
718
719        // Update all configured networks before initiating network selection.
720        updateConfiguredNetworks();
721
722        // Update the registered network evaluators.
723        for (NetworkEvaluator registeredEvaluator : mEvaluators) {
724            registeredEvaluator.update(scanDetails);
725        }
726
727        // Filter out unwanted networks.
728        mFilteredNetworks = filterScanResults(scanDetails, bssidBlacklist,
729                connected && wifiInfo.score >= WIFI_POOR_SCORE, currentBssid);
730        if (mFilteredNetworks.size() == 0) {
731            return null;
732        }
733
734        // Determine the weight for the last user selection
735        final int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork();
736        final double lastSelectionWeight = calculateLastSelectionWeight();
737        final ArraySet<Integer> mNetworkIds = new ArraySet<>();
738
739        // Go through the registered network evaluators in order
740        WifiConfiguration selectedNetwork = null;
741        WifiCandidates wifiCandidates = new WifiCandidates(mWifiScoreCard);
742        if (currentNetwork != null) {
743            wifiCandidates.setCurrent(currentNetwork.networkId, currentBssid);
744        }
745        for (NetworkEvaluator registeredEvaluator : mEvaluators) {
746            localLog("About to run " + registeredEvaluator.getName() + " :");
747            WifiConfiguration choice = registeredEvaluator.evaluateNetworks(
748                    new ArrayList<>(mFilteredNetworks), currentNetwork, currentBssid, connected,
749                    untrustedNetworkAllowed,
750                    (scanDetail, config, score) -> {
751                        if (config != null) {
752                            mConnectableNetworks.add(Pair.create(scanDetail, config));
753                            mNetworkIds.add(config.networkId);
754                            if (config.networkId == lastUserSelectedNetworkId) {
755                                wifiCandidates.add(scanDetail, config,
756                                        registeredEvaluator.getId(), score, lastSelectionWeight);
757                            } else {
758                                wifiCandidates.add(scanDetail, config,
759                                        registeredEvaluator.getId(), score);
760                            }
761                            mWifiMetrics.setNominatorForNetwork(config.networkId,
762                                    evaluatorIdToNominatorId(registeredEvaluator.getId()));
763                        }
764                    });
765            if (choice != null && !mNetworkIds.contains(choice.networkId)) {
766                Log.wtf(TAG, registeredEvaluator.getName()
767                        + " failed to report choice with noConnectibleListener");
768            }
769            if (selectedNetwork == null && choice != null) {
770                selectedNetwork = choice; // First one wins
771                localLog(registeredEvaluator.getName() + " selects "
772                        + WifiNetworkSelector.toNetworkString(selectedNetwork));
773            }
774        }
775
776        if (mConnectableNetworks.size() != wifiCandidates.size()) {
777            localLog("Connectable: " + mConnectableNetworks.size()
778                    + " Candidates: " + wifiCandidates.size());
779        }
780
781        // Update the NetworkSelectionStatus in the configs for the current candidates
782        // This is needed for the legacy user connect choice, at least
783        Collection<Collection<WifiCandidates.Candidate>> groupedCandidates =
784                wifiCandidates.getGroupedCandidates();
785        for (Collection<WifiCandidates.Candidate> group: groupedCandidates) {
786            WifiCandidates.Candidate best = null;
787            for (WifiCandidates.Candidate candidate: group) {
788                // Of all the candidates with the same networkId, choose the
789                // one with the smallest evaluatorId, and break ties by
790                // picking the one with the highest score.
791                if (best == null
792                        || candidate.getEvaluatorId() < best.getEvaluatorId()
793                        || (candidate.getEvaluatorId() == best.getEvaluatorId()
794                            && candidate.getEvaluatorScore() > best.getEvaluatorScore())) {
795                    best = candidate;
796                }
797            }
798            if (best != null) {
799                ScanDetail scanDetail = best.getScanDetail();
800                if (scanDetail != null) {
801                    mWifiConfigManager.setNetworkCandidateScanResult(best.getNetworkConfigId(),
802                            scanDetail.getScanResult(), best.getEvaluatorScore());
803                }
804            }
805        }
806
807        ArrayMap<Integer, Integer> experimentNetworkSelections = new ArrayMap<>(); // for metrics
808
809        final int legacySelectedNetworkId = selectedNetwork == null
810                ? WifiConfiguration.INVALID_NETWORK_ID
811                : selectedNetwork.networkId;
812
813        int selectedNetworkId = legacySelectedNetworkId;
814
815        // Run all the CandidateScorers
816        boolean legacyOverrideWanted = true;
817        final WifiCandidates.CandidateScorer activeScorer = getActiveCandidateScorer();
818        for (WifiCandidates.CandidateScorer candidateScorer : mCandidateScorers.values()) {
819            WifiCandidates.ScoredCandidate choice;
820            try {
821                choice = wifiCandidates.choose(candidateScorer);
822            } catch (RuntimeException e) {
823                Log.wtf(TAG, "Exception running a CandidateScorer", e);
824                continue;
825            }
826            int networkId = choice.candidateKey == null
827                    ? WifiConfiguration.INVALID_NETWORK_ID
828                    : choice.candidateKey.networkId;
829            String chooses = " would choose ";
830            if (candidateScorer == activeScorer) {
831                chooses = " chooses ";
832                legacyOverrideWanted = candidateScorer.userConnectChoiceOverrideWanted();
833                selectedNetworkId = networkId;
834            }
835            String id = candidateScorer.getIdentifier();
836            int expid = experimentIdFromIdentifier(id);
837            localLog(id + chooses + networkId
838                    + " score " + choice.value + "+/-" + choice.err
839                    + " expid " + expid);
840            experimentNetworkSelections.put(expid, networkId);
841        }
842
843        // Update metrics about differences in the selections made by various methods
844        final int activeExperimentId = activeScorer == null ? LEGACY_CANDIDATE_SCORER_EXP_ID
845                : experimentIdFromIdentifier(activeScorer.getIdentifier());
846        experimentNetworkSelections.put(LEGACY_CANDIDATE_SCORER_EXP_ID, legacySelectedNetworkId);
847        for (Map.Entry<Integer, Integer> entry :
848                experimentNetworkSelections.entrySet()) {
849            int experimentId = entry.getKey();
850            if (experimentId == activeExperimentId) continue;
851            int thisSelectedNetworkId = entry.getValue();
852            mWifiMetrics.logNetworkSelectionDecision(experimentId, activeExperimentId,
853                    selectedNetworkId == thisSelectedNetworkId,
854                    groupedCandidates.size());
855        }
856
857        // Get a fresh copy of WifiConfiguration reflecting any scan result updates
858        selectedNetwork = mWifiConfigManager.getConfiguredNetwork(selectedNetworkId);
859        if (selectedNetwork != null && legacyOverrideWanted) {
860            selectedNetwork = overrideCandidateWithUserConnectChoice(selectedNetwork);
861            mLastNetworkSelectionTimeStamp = mClock.getElapsedSinceBootMillis();
862        }
863        return selectedNetwork;
864    }

 

303    private boolean isNetworkSelectionNeeded(List<ScanDetail> scanDetails, WifiInfo wifiInfo,
304                        boolean connected, boolean disconnected) {
305        if (scanDetails.size() == 0) {
306            localLog("Empty connectivity scan results. Skip network selection.");
307            return false;
308        }
309
310        if (connected) {
311            // Is roaming allowed?
312            if (!mEnableAutoJoinWhenAssociated) {
313                localLog("Switching networks in connected state is not allowed."
314                        + " Skip network selection.");
315                return false;
316            }
317
318            // Has it been at least the minimum interval since last network selection?
319            if (mLastNetworkSelectionTimeStamp != INVALID_TIME_STAMP) {
320                long gap = mClock.getElapsedSinceBootMillis()
321                            - mLastNetworkSelectionTimeStamp;
322                if (gap < MINIMUM_NETWORK_SELECTION_INTERVAL_MS) {
323                    localLog("Too short since last network selection: " + gap + " ms."
324                            + " Skip network selection.");
325                    return false;
326                }
327            }
328
329            if (isCurrentNetworkSufficient(wifiInfo, scanDetails)) {
330                localLog("Current connected network already sufficient. Skip network selection.");
331                return false;
332            } else {
333                localLog("Current connected network is not sufficient.");
334                return true;
335            }
336        } else if (disconnected) {
337            return true;
338        } else {
339            // No network selection if ClientModeImpl is in a state other than
340            // CONNECTED or DISCONNECTED.
341            localLog("ClientModeImpl is in neither CONNECTED nor DISCONNECTED state."
342                    + " Skip network selection.");
343            return false;
344        }
345    }

 

221    private boolean isCurrentNetworkSufficient(WifiInfo wifiInfo, List<ScanDetail> scanDetails) {
222        // Currently connected?
223        if (wifiInfo.getSupplicantState() != SupplicantState.COMPLETED) {
224            localLog("No current connected network.");
225            return false;
226        } else {
227            localLog("Current connected network: " + wifiInfo.getSSID()
228                    + " , ID: " + wifiInfo.getNetworkId());
229        }
230
231        int currentRssi = wifiInfo.getRssi();
232        boolean hasQualifiedRssi = currentRssi
233                > mScoringParams.getSufficientRssi(wifiInfo.getFrequency());
234        boolean hasActiveStream = (wifiInfo.txSuccessRate > mStayOnNetworkMinimumTxRate)
235                || (wifiInfo.rxSuccessRate > mStayOnNetworkMinimumRxRate);
236        if (hasQualifiedRssi && hasActiveStream) {
237            localLog("Stay on current network because of good RSSI and ongoing traffic");
238            return true;
239        }
240        WifiConfiguration network =
241                mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());
242
243        if (network == null) {
244            localLog("Current network was removed.");
245            return false;
246        }
247
248        if (mWifiConfigManager.getLastSelectedNetwork() == network.networkId
249                && (mClock.getElapsedSinceBootMillis()
250                    - mWifiConfigManager.getLastSelectedTimeStamp())
251                <= LAST_USER_SELECTION_SUFFICIENT_MS) {
252            localLog("Current network is recently user-selected.");
253            return true;
254        }
255
256        // OSU (Online Sign Up) network for Passpoint Release 2 is sufficient network.
257        if (network.osu) {
258            return true;
259        }
260
261        // Ephemeral network is not qualified.
262        if (wifiInfo.isEphemeral()) {
263            localLog("Current network is an ephemeral one.");
264            return false;
265        }
266
267        if (wifiInfo.is24GHz()) {
268            // 2.4GHz networks is not qualified whenever 5GHz is available
269            if (is5GHzNetworkAvailable(scanDetails)) {
270                localLog("Current network is 2.4GHz. 5GHz networks available.");
271                return false;
272            }
273        }
274        if (!hasQualifiedRssi) {
275            localLog("Current network RSSI[" + currentRssi + "]-acceptable but not qualified.");
276            return false;
277        }
278
279        // Open network is not qualified.
280        if (WifiConfigurationUtil.isConfigForOpenNetwork(network)) {
281            localLog("Current network is a open one.");
282            return false;
283        }
284
285        // Network with no internet access reports is not qualified.
286        if (network.numNoInternetAccessReports > 0 && !network.noInternetAccessExpected) {
287            localLog("Current network has [" + network.numNoInternetAccessReports
288                    + "] no-internet access reports.");
289            return false;
290        }
291        return true;
292    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值