Wifi 评分机制分析
从android N开始,引入了wifi评分机制,选择wifi的时候会通过评分来选择。
android O源码
frameworks\opt\net\wifi\service\java\com\android\server\wifi\SavedNetworkEvaluator.java
private int calculateBssidScore(ScanResult scanResult, WifiConfiguration network,
WifiConfiguration currentNetwork, String currentBssid,
StringBuffer sbuf) {
int score = 0;
// 判断信号是否为5GHz
boolean is5GHz = scanResult.is5GHz();
sbuf.append("[ ").append(scanResult.SSID).append(" ").append(scanResult.BSSID)
.append(" RSSI:").append(scanResult.level).append(" ] ");
// Calculate the RSSI score.
int rssiSaturationThreshold = is5GHz ? mThresholdSaturatedRssi5 : mThresholdSaturatedRssi24;
// 根据wifi的信号等级来获取rssi
int rssi = scanResult.level < rssiSaturationThreshold ? scanResult.level
: rssiSaturationThreshold;
score += (rssi + mRssiScoreOffset) * mRssiScoreSlope;
sbuf.append(" RSSI score: ").append(score).append(",");
// 5GHz band bonus.
if (is5GHz) {
score += mBand5GHzAward; // score += 40
sbuf.append(" 5GHz bonus: ").append(mBand5GHzAward).append(",");
}
// 之前连接过会有奖励
// Last user selection award.
int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork();
if (lastUserSelectedNetworkId != WifiConfiguration.INVALID_NETWORK_ID
&& lastUserSelectedNetworkId == network.networkId) {
// 开机时间减去连接的时间戳,得到的时间就是连接的时间到现在总共多久
long timeDifference = mClock.getElapsedSinceBootMillis()
- mWifiConfigManager.getLastSelectedTimeStamp();
if (timeDifference > 0) {
int bonus = mLastSelectionAward - (int) (timeDifference / 1000 / 60);
score += bonus > 0 ? bonus : 0;
sbuf.append(" User selection ").append(timeDifference / 1000 / 60)
.append(" minutes ago, bonus: ").append(bonus).append(",");
}
}
// Same network award.
// 当前正在连接的SSID也会有奖励
if (currentNetwork != null
&& (network.networkId == currentNetwork.networkId
//TODO(b/36788683): re-enable linked configuration check
/* || network.isLinked(currentNetwork) */)) {
score += mSameNetworkAward;
sbuf.append(" Same network bonus: ").append(mSameNetworkAward).append(",");
// 如果支持漫游,也会有漫游奖励
// When firmware roaming is supported, equivalent BSSIDs (the ones under the
// same network as the currently connected one) get the same BSSID award.
// 漫游奖励,SSID相同,BSSID不同。
if (mConnectivityHelper.isFirmwareRoamingSupported()
&& currentBssid != null && !currentBssid.equals(scanResult.BSSID)) {
score += mSameBssidAward;
sbuf.append(" Equivalent BSSID bonus: ").append(mSameBssidAward).append(",");
}
}
// Same BSSID award.
if (currentBssid != null && currentBssid.equals(scanResult.BSSID)) {
score += mSameBssidAward;
sbuf.append(" Same BSSID bonus: ").append(mSameBssidAward).append(",");
}
// Security award.
// 不是开放的网络,也会有奖励
if (!WifiConfigurationUtil.isConfigForOpenNetwork(network)) {
score += mSecurityAward;
sbuf.append(" Secure network bonus: ").append(mSecurityAward).append(",");
}
sbuf.append(" ## Total score: ").append(score).append("\n");
return score;
}
/**
* Evaluate all the networks from the scan results and return
* the WifiConfiguration of the network chosen for connection.
*
* @return configuration of the chosen network;
* null if no network in this category is available.
*/
public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
WifiConfiguration currentNetwork, String currentBssid, boolean connected,
boolean untrustedNetworkAllowed,
List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks) {
int highestScore = Integer.MIN_VALUE;
ScanResult scanResultCandidate = null;
WifiConfiguration candidate = null;
StringBuffer scoreHistory = new StringBuffer();
for (ScanDetail scanDetail : scanDetails) {
ScanResult scanResult = scanDetail.getScanResult();
int highestScoreOfScanResult = Integer.MIN_VALUE; // 0x80000000
int candidateIdOfScanResult = WifiConfiguration.INVALID_NETWORK_ID; // -1
// One ScanResult can be associated with more than one networks, hence we calculate all
// the scores and use the highest one as the ScanResult's score.
List<WifiConfiguration> associatedConfigurations = null;
WifiConfiguration associatedConfiguration =
mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail);
if (associatedConfiguration == null) {
continue;
} else {
associatedConfigurations =
new ArrayList<>(Arrays.asList(associatedConfiguration));
}
for (WifiConfiguration network : associatedConfigurations) {
/**
* Ignore Passpoint and Ephemeral networks. They are configured networks,
* but without being persisted to the storage. They are evaluated by
* {@link PasspointNetworkEvaluator} and {@link ScoredNetworkEvaluator}
* respectively.
*/
if (network.isPasspoint() || network.isEphemeral()) {
continue;
}
WifiConfiguration.NetworkSelectionStatus status =
network.getNetworkSelectionStatus();
status.setSeenInLastQualifiedNetworkSelection(true);
if (!status.isNetworkEnabled()) {
continue;
} else if (network.BSSID != null && !network.BSSID.equals("any")
&& !network.BSSID.equals(scanResult.BSSID)) {
// App has specified the only BSSID to connect for this
// configuration. So only the matching ScanResult can be a candidate.
localLog("Network " + WifiNetworkSelector.toNetworkString(network)
+ " has specified BSSID " + network.BSSID + ". Skip "
+ scanResult.BSSID);
continue;
} else if (TelephonyUtil.isSimConfig(network)
&& !mWifiConfigManager.isSimPresent()) {
// Don't select if security type is EAP SIM/AKA/AKA' when SIM is not present.
continue;
}
// 计算分数
int score = calculateBssidScore(scanResult, network, currentNetwork, currentBssid,
scoreHistory);
// Set candidate ScanResult for all saved networks to ensure that users can
// override network selection. See WifiNetworkSelector#setUserConnectChoice.
// TODO(b/36067705): consider alternative designs to push filtering/selecting of
// user connect choice networks to RecommendedNetworkEvaluator.
if (score > status.getCandidateScore() || (score == status.getCandidateScore()
&& status.getCandidate() != null
&& scanResult.level > status.getCandidate().level)) {
// 重新设置candidate
mWifiConfigManager.setNetworkCandidateScanResult(
network.networkId, scanResult, score);
}
// If the network is marked to use external scores, or is an open network with
// curate saved open networks enabled, do not consider it for network selection.
if (network.useExternalScores) {
localLog("Network " + WifiNetworkSelector.toNetworkString(network)
+ " has external score.");
continue;
}
// 判断是否在扫描的列表中评分最高
if (score > highestScoreOfScanResult) {
highestScoreOfScanResult = score;
// 保存networkId
candidateIdOfScanResult = network.networkId;
}
}
if (connectableNetworks != null) {
connectableNetworks.add(Pair.create(scanDetail,
mWifiConfigManager.getConfiguredNetwork(candidateIdOfScanResult)));
}
// 根据评分以及level来判断选择最合适的candidate
if (highestScoreOfScanResult > highestScore
|| (highestScoreOfScanResult == highestScore
&& scanResultCandidate != null
&& scanResult.level > scanResultCandidate.level)) {
highestScore = highestScoreOfScanResult;
scanResultCandidate = scanResult;
mWifiConfigManager.setNetworkCandidateScanResult(
candidateIdOfScanResult, scanResultCandidate, highestScore);
// Reload the network config with the updated info.
candidate = mWifiConfigManager.getConfiguredNetwork(candidateIdOfScanResult);
}
}
if (scoreHistory.length() > 0) {
localLog("\n" + scoreHistory.toString());
}
if (scanResultCandidate == null) {
localLog("did not see any good candidates.");
}
return candidate;
}
}
2018-7-12, Shenzhen
Wifi 评分机制分析的更多相关文章
- Android 8.0/9.0 wifi 自动连接评分机制
前言 Android N wifi auto connect流程分析 Android N selectQualifiedNetwork分析 Wifi自动连接时的评分机制 今天了解了一下Wifi自动连接 ...
- lucene 的评分机制
lucene 的评分机制 elasticsearch是基于lucene的,所以他的评分机制也是基于lucene的.评分就是我们搜索的短语和索引中每篇文档的相关度打分. 如果没有干预评分算法的时候,每次 ...
- Elasticseach的评分机制
lucene 的评分机制 elasticsearch是基于lucene的,所以他的评分机制也是基于lucene的.评分就是我们搜索的短语和索引中每篇文档的相关度打分. 如果没有干预评分算法的时候,每次 ...
- Linux mips64r2 PCI中断路由机制分析
Linux mips64r2 PCI中断路由机制分析 本文主要分析mips64r2 PCI设备中断路由原理和irq号分配实现方法,并尝试回答如下问题: PCI设备驱动中断注册(request_irq) ...
- IOS Table中Cell的重用reuse机制分析
IOS Table中Cell的重用reuse机制分析 技术交流新QQ群:414971585 创建UITableViewController子类的实例后,IDE生成的代码中有如下段落: - (UITab ...
- 您还有心跳吗?超时机制分析(java)
注:本人是原作者,首发于并发编程网(您还有心跳吗?超时机制分析),此文结合那里的留言作了一些修改. 问题描述 在C/S模式中,有时我们会长时间保持一个连接,以避免频繁地建立连接,但同时,一般会有一个超 ...
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- android wifi ANR问题分析总结
android wifi ANR问题分析总结 1 看看main进程阻塞在那里? 2 调用关系的函数阻塞在那里? 3 最终阻塞函数的阻塞前的log以及状态
- Linux信号(signal) 机制分析
Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...
随机推荐
- nginx upstream 常用的几种调度方式
nginx可以根据客户IP进行负载均衡,在upstream里设置ip_hash,以可以对同一个C类地址段的客户端选择同一个后端服务器,除非那个后端服务器宕了才会换一个.C类地址:C类地址第1字节.第2 ...
- Angular的重和利
1.第一重:TypeScript,TypeScript语言的特性还是比较丰富的,而且一直在发展,再就是跨语言集成问题,要想Nice对第三方lib做集成,需要自己写d.ts,针对有些第三方库,这件事情有 ...
- quick3.3final版创建项目报错解决
PHP Notice: Undefined index: QUICK_V3_ROOT in 405,469,497,520,551这5行代码都访问了一个环境变量$_ENV['QUICK_V3_ROO ...
- (转)Making 1 million requests with python-aiohttp
转自:https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html Making 1 millio ...
- 【驱动】网卡驱动·linux内核网络分层结构
Preface Linux内核对网络驱动程序使用统一的接口,并且对于网络设备采用面向对象的思想设计. Linux内核采用分层结构处理网络数据包.分层结构与网络协议的结构匹配,既能简化数据包处理流程 ...
- Spring Boot 中使用WebJars
WebJars能使Maven的依赖管理支持OSS的JavaScript库/CSS库,比如jQuery.Bootstrap等: WebJars是将Web前端Javascript和CSS等资源打包成Jav ...
- Python3回文相关算法小结
[本文出自天外归云的博客园] 总结一下关于回文相关的算法: 判断字符串本身是否是回文 返回字符串中的所有子串 找到字符串中包含的所有回文 判断字符串中是否包含回文 将字符串变成一个不包含回文的字符串 ...
- tf.Variable
tf.Variable __init__( initial_value=None, trainable=True, collections=None, validate_shape=True, cac ...
- rapidjson使用总结
Reference: https://blog.csdn.net/elloop/article/details/49908689 rapidjson简介 rapidjson是腾讯的开源json解析框 ...
- 浅析notifyDataSetChanged内部工作流程
Reference: http://blog.csdn.net/hp910315/article/details/47174531 首先我们知道notifyDataSetChanged是Adater的 ...