android wifi scan and auto re-connect
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 range689 * @param bssidBlacklist Blacklisted BSSIDs690 * @param wifiInfo Currently connected network691 * @param connected True if the device is connected692 * @param disconnected True if the device is disconnected693 * @param untrustedNetworkAllowed True if untrusted networks are allowed for connection694 * @return Configuration of the selected network, or Null if nothing695 */696 @Nullable697 public WifiConfiguration selectNetwork(ListscanDetails,698 HashSet 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 }706707 WifiConfiguration currentNetwork =708 mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());709710 // Always get the current BSSID from WifiInfo in case that firmware initiated711 // roaming happened.712 String currentBssid = wifiInfo.getBSSID();713714 // Shall we start network selection at all?715 if (!isNetworkSelectionNeeded(scanDetails, wifiInfo, connected, disconnected)) {716 return null;717 }718719 // Update all configured networks before initiating network selection.720 updateConfiguredNetworks();721722 // Update the registered network evaluators.723 for (NetworkEvaluator registeredEvaluator : mEvaluators) {724 registeredEvaluator.update(scanDetails);725 }726727 // 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 }733734 // Determine the weight for the last user selection735 final int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork();736 final double lastSelectionWeight = calculateLastSelectionWeight();737 final ArraySet mNetworkIds = new ArraySet<>();738739 // Go through the registered network evaluators in order740 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 wins771 localLog(registeredEvaluator.getName() + " selects "772 + WifiNetworkSelector.toNetworkString(selectedNetwork));773 }774 }775776 if (mConnectableNetworks.size() != wifiCandidates.size()) {777 localLog("Connectable: " + mConnectableNetworks.size()778 + " Candidates: " + wifiCandidates.size());779 }780781 // Update the NetworkSelectionStatus in the configs for the current candidates782 // This is needed for the legacy user connect choice, at least783 Collection > groupedCandidates =784 wifiCandidates.getGroupedCandidates();785 for (Collection group: groupedCandidates) {786 WifiCandidates.Candidate best = null;787 for (WifiCandidates.Candidate candidate: group) {788 // Of all the candidates with the same networkId, choose the789 // one with the smallest evaluatorId, and break ties by790 // picking the one with the highest score.791 if (best == null792 || 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 }806807 ArrayMap experimentNetworkSelections = new ArrayMap<>(); // for metrics808809 final int legacySelectedNetworkId = selectedNetwork == null810 ? WifiConfiguration.INVALID_NETWORK_ID811 : selectedNetwork.networkId;812813 int selectedNetworkId = legacySelectedNetworkId;814815 // Run all the CandidateScorers816 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 == null827 ? WifiConfiguration.INVALID_NETWORK_ID828 : 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 + networkId838 + " score " + choice.value + "+/-" + choice.err839 + " expid " + expid);840 experimentNetworkSelections.put(expid, networkId);841 }842843 // Update metrics about differences in the selections made by various methods844 final int activeExperimentId = activeScorer == null ? LEGACY_CANDIDATE_SCORER_EXP_ID845 : experimentIdFromIdentifier(activeScorer.getIdentifier());846 experimentNetworkSelections.put(LEGACY_CANDIDATE_SCORER_EXP_ID, legacySelectedNetworkId);847 for (Map.Entry 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 }856857 // Get a fresh copy of WifiConfiguration reflecting any scan result updates858 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(ListscanDetails, 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 }309310 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 }317318 // 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 }328329 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 than340 // 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, ListscanDetails) {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 }230231 int currentRssi = wifiInfo.getRssi();232 boolean hasQualifiedRssi = currentRssi233 > 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());242243 if (network == null) {244 localLog("Current network was removed.");245 return false;246 }247248 if (mWifiConfigManager.getLastSelectedNetwork() == network.networkId249 && (mClock.getElapsedSinceBootMillis()250 - mWifiConfigManager.getLastSelectedTimeStamp())251 <= LAST_USER_SELECTION_SUFFICIENT_MS) {252 localLog("Current network is recently user-selected.");253 return true;254 }255256 // OSU (Online Sign Up) network for Passpoint Release 2 is sufficient network.257 if (network.osu) {258 return true;259 }260261 // Ephemeral network is not qualified.262 if (wifiInfo.isEphemeral()) {263 localLog("Current network is an ephemeral one.");264 return false;265 }266267 if (wifiInfo.is24GHz()) {268 // 2.4GHz networks is not qualified whenever 5GHz is available269 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 }278279 // Open network is not qualified.280 if (WifiConfigurationUtil.isConfigForOpenNetwork(network)) {281 localLog("Current network is a open one.");282 return false;283 }284285 // Network with no internet access reports is not qualified.286 if (network.numNoInternetAccessReports > 0 && !network.noInternetAccessExpected) {287 localLog("Current network has [" + network.numNoInternetAccessReports288 + "] no-internet access reports.");289 return false;290 }291 return true;292 }
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- Android(安卓)- 判断当前网络环境、隐藏软键盘、动态监测及获取
- android文件存储的五种方式简介
- 请求网络数据后更新视图
- Android(安卓)Studio Build Output 汉字乱码
- Android开发之MAC下无法连接Android设备
- jni中使用libcurl做网络开发
- android httpclient https 单向连接tomcat
- Android学习笔记之文件的保存与读取