这个评分器比较简单,其主要考虑因素就是RSSI。我们直接先上代码再分析
private ScoredCandidate scoreCandidate(Candidate candidate) {
final int rssi = candidate.getScanRssi();
final int rssiEntryThreshold = mScoringParams.getEntryRssi(candidate.getFrequency());
double score = shapeFunction(rssi) - shapeFunction(rssiEntryThreshold);
// If we are below the entry threshold, make the score more negative
if (score < 0.0) score *= 2.0;
// The gain is approximately the derivative of shapeFunction at the given rssi
// This is used to estimate the error
double gain = shapeFunction(rssi + 0.5)
- shapeFunction(rssi - 0.5);
// Prefer 5GHz/6GHz when all are strong, but at the fringes, 2.4 might be better
// Typically the entry rssi is lower for the 2.4 band, which provides the fringe boost
if (ScanResult.is24GHz(candidate.getFrequency())) {
score *= LOW_BAND_FACTOR; /* LOW_BAND_FACTOR = 0.25 */
gain *= LOW_BAND_FACTOR;
}
// A recently selected network gets a large boost
score += candidate.getLastSelectionWeight() * LAST_SELECTION_BOOST;
// Hysteresis to prefer staying on the current network.
if (candidate.isCurrentNetwork()) {
score += CURRENT_NETWORK_BOOST;
}
if (!candidate.isOpenNetwork()) {
score += SECURITY_AWARD;
}
return new ScoredCandidate(score, TYPICAL_SCAN_RSSI_STD * gain,
USE_USER_CONNECT_CHOICE, candidate);
}
下面是对上面代码的详细分析
-
初始打分: 先通过
shapeFunction()
对rssi进行初始打分。 这里shapeFunction()
是一个单调递增的指数类函数。 -
弱信号惩罚: 如果
score
小于0(表示信号比入口阈值Entry Rssi更弱),则会将其乘以2 进一步惩罚 -
增益估算: 增益近似为给定 rssi 处
shapeFunction()
的导数。这用于估计误差。 -
频段偏好: 由于5G/6G速率更快,干扰更小,所以更偏向于5G。但是弱信号时,2.4G表现更好。由于2.4G 的Entry rssi更低,所以可以理解为此时2.4G 的分数会更高。2.4G时 score 和 gain 都乘以
LOW_BAND_FACTOR = 0.25
-
最新选择奖励:
getLastSelectionWeight()
对于最近一次选择的网络,根据时间差计算出权重,给与最高250分的奖励。
这里的最近一次是有限制的,由ScoringParams
的lastSelectionMinutes
指定,默认是480min,也就是8H.
权重的计算方法WifiNetworkSelector.calculateLastSelectionWeight(),算法也很简单。
假设 上次被选择的时间为 t1, 当前时间t2,lastSelectionMinutes默认480min
那么最终计算出的权重是
if t2 - t1 > 480min:
return 0;
else
return 1 - (t2-t1)/(480*60*1000)
所以,距离时间越长分数就越低。
-
当前网络奖励: 如果当前已连接,加
CURRENT_NETWORK_BOOST = 22
分。尽量保证当前连接,避免频繁或者不必要的切换。 -
安全性奖励: 非open网络,加
SECURITY_AWARD = 44
分。
最后我们来看看shapeFunction()
的实现。
private static double unscaledShapeFunction(double rssi) {
return -Math.exp(-rssi * BELS_PER_DECIBEL);
}
private static final double BELS_PER_DECIBEL = 0.1;
private static final double RESCALE_FACTOR = 100.0 / (
unscaledShapeFunction(0.0) - unscaledShapeFunction(-85.0));
private static double shapeFunction(double rssi) {
return unscaledShapeFunction(rssi) * RESCALE_FACTOR;
}
实际上它将rssi转换成了一个以自然常数e为底的指数函数,从下面的函数图形可以看出,它是一个单调递增的函数,在rssi小于-60的时候,函数上升的特别快,从-60开始,逐渐平缓,大于-40时,几乎不会有太大增长。

最后的函数如下
100
1
−
e
8.5
×
1
e
0.1
x
\frac{100}{1-e^{8.5} } \times \frac{1}{e^{0.1x} }
1−e8.5100×e0.1x1
RESCALE_FACTOR = 100.0 / (unscaledShapeFunction(0.0) - unscaledShapeFunction(-85.0))
是为了对图像进行缩放让有意义的点落在较为合理的区间。
实际情况下,较弱的信号可能会导致较大的性能下降,因此在打分时对弱信号会进行更为严厉的处罚;对于强信号来说,即使信号减弱,性能下降或许也不明显,因此评分的降低就更为平缓。