Android Wifi
记录下学习Android 10源码中有关Wifi的知识点
知识点
WEP
无线加密协议(英语:Wireless Encryption Protocol)
WPA
全名为 Wi-Fi Protected Access
(Wi-Fi网络安全存取)
PSK
,预共享密钥模式(pre-shared key (PSK),又称为"-Personal",即“-个人模式”)是针对承担不起802.1X
认证服务器的成本和复杂度的家庭或小型公司网络设计和使用的
SAE
(Simultaneous Authentication of Equals):对等实体同时验证
OWE
(Opportunistic Wireless Encryption)机会性无限加密
EAP
(Extensible Authentication Protocol)是一种支持多种验证方式的协议框架
Passpoint
WiFi联盟宣称,它的Passpoint计划目标是让WiFi变成网络服务商的扩展功能,WiFi设备能从一个热点漫游到另一个热点,无需手动输入密码,一切都是无缝切换的,
Hotspot 2.0 OSU
参考:
通常客户端需要手动进行身份验证才可以接入无线网络。运营商希望客户端能够在移动网络和无线网络之间无缝漫游,即客户端根据当前网络环境自动接入合适的无线网络,并无需手工进行身份验证。针对这一需求Wi-Fi联盟推出了Hotspot 2.0协议,该协议可以使客户端自动发现、注册并关联和自己移动网络服务提供商有漫游协议的无线Wi-Fi网络,实现移动数据网络和无线Wi-Fi网络的自动切换,或者无线Wi-Fi网络的不同无线服务的自动切换。
WPA3 和 Wi-Fi Enhanced Open
参考Android官方文档:
WifiSettings
位于packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java
WifiEnabler
位于packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java
WifiEnabler处理的是开启or关闭wifi
WifiTracker
WifiTracker
位于frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
1.获取最新的scan result和wifi config
通过fetchScansAndConfigsAndUpdateAccessPoints
方法获取最新的scan result和wifi config
通过filterScanResultsByCapabilities
方法,过滤scan结果中不支持的network
最后更新access poinit,通过调用updateAccessPoints(filteredScanResults, configs)
方法
1.getConfiguredNetworks()
方法返回的是,为当前前台用户配置的所有网络的列表
本人测试了下,连接2个热点后,mWifiManager.getConfiguredNetworks()
返回值如下:
2.updateAccessPoints
更新内部接入点列表
/** Update the internal list of access points. */
private void updateAccessPoints(final List<ScanResult> newScanResults,
List<WifiConfiguration> configs) {
// Map configs and scan results necessary to make AccessPoints
final Map<String, WifiConfiguration> configsByKey = new ArrayMap(configs.size());
if (configs != null) {
for (WifiConfiguration config : configs) {
configsByKey.put(AccessPoint.getKey(config), config);
}
}
WifiConfiguration connectionConfig = null;
if (mLastInfo != null) {//mLastInfo为getConnectionInfo获取的WifiInfo
//通过当前WifiInfo,获取WifiConfiguration配置信息
connectionConfig = getWifiConfigurationForNetworkId(mLastInfo.getNetworkId(), configs);
}
// Rather than dropping and reacquiring the lock multiple times in this method, we lock
// once for efficiency of lock acquisition time and readability
synchronized (mLock) {
ArrayMap<String, List<ScanResult>> scanResultsByApKey =
updateScanResultCache(newScanResults);
// Swap the current access points into a cached list for maintaining AP listeners
List<AccessPoint> cachedAccessPoints;
cachedAccessPoints = new ArrayList<>(mInternalAccessPoints);
ArrayList<AccessPoint> accessPoints = new ArrayList<>();
final List<NetworkKey> scoresToRequest = new ArrayList<>();
for (Map.Entry<String, List<ScanResult>> entry : scanResultsByApKey.entrySet()) {
for (ScanResult result : entry.getValue()) {
NetworkKey key = NetworkKey.createFromScanResult(result);
if (key != null && !mRequestedScores.contains(key)) {
scoresToRequest.add(key);
}
}
AccessPoint accessPoint =
getCachedOrCreate(entry.getValue(), cachedAccessPoints);
// Update the matching config if there is one, to populate saved network info
accessPoint.update(configsByKey.get(entry.getKey()));
accessPoints.add(accessPoint);
}
List<ScanResult> cachedScanResults = new ArrayList<>(mScanResultCache.values());
// Add a unique Passpoint AccessPoint for each Passpoint profile's FQDN.
accessPoints.addAll(updatePasspointAccessPoints(
mWifiManager.getAllMatchingWifiConfigs(cachedScanResults), cachedAccessPoints));
// Add OSU Provider AccessPoints
accessPoints.addAll(updateOsuAccessPoints(
mWifiManager.getMatchingOsuProviders(cachedScanResults), cachedAccessPoints));
if (mLastInfo != null && mLastNetworkInfo != null) {
for (AccessPoint ap : accessPoints) {
ap.update(connectionConfig, mLastInfo, mLastNetworkInfo);
}
}
// If there were no scan results, create an AP for the currently connected network (if
// it exists).
if (accessPoints.isEmpty() && connectionConfig != null) {
AccessPoint activeAp = new AccessPoint(mContext, connectionConfig);
activeAp.update(connectionConfig, mLastInfo, mLastNetworkInfo);
accessPoints.add(activeAp);
scoresToRequest.add(NetworkKey.createFromWifiInfo(mLastInfo));
}
requestScoresForNetworkKeys(scoresToRequest);
for (AccessPoint ap : accessPoints) {
ap.update(mScoreCache, mNetworkScoringUiEnabled, mMaxSpeedLabelScoreCacheAge);
}
// Pre-sort accessPoints to speed preference insertion
Collections.sort(accessPoints);
// Log accesspoints that are being removed
if (DBG()) {
Log.d(TAG,
"------ Dumping AccessPoints that were not seen on this scan ------");
for (AccessPoint prevAccessPoint : mInternalAccessPoints) {
String prevTitle = prevAccessPoint.getTitle();
boolean found = false;
for (AccessPoint newAccessPoint : accessPoints) {
if (newAccessPoint.getTitle() != null && newAccessPoint.getTitle()
.equals(prevTitle)) {
found = true;
break;
}
}
if (!found)
Log.d(TAG, "Did not find " + prevTitle + " in this scan");
}
Log.d(TAG,
"---- Done dumping AccessPoints that were not seen on this scan ----");
}
mInternalAccessPoints.clear();
mInternalAccessPoints.addAll(accessPoints);
}
conditionallyNotifyListeners();
}
WifiManager
的getConnectionInfo()
获取的是有关当前 Wi-Fi 连接的动态信息
updateScanResultCache
方法的理解,字面意思是:更新扫描结果的缓存
private ArrayMap<String, List<ScanResult>> updateScanResultCache(
final List<ScanResult> newResults) {
// TODO(sghuman): Delete this and replace it with the Map of Ap Keys to ScanResults for
// memory efficiency
for (ScanResult newResult : newResults) {
if (newResult.SSID == null || newResult.SSID.isEmpty()) {
continue;
}
//BSSID作为主键
mScanResultCache.put(newResult.BSSID, newResult);
}
// Evict old results in all conditions 移除旧的result
evictOldScans();
ArrayMap<String, List<ScanResult>> scanResultsByApKey = new ArrayMap<>();
for (ScanResult result : mScanResultCache.values()) {
// Ignore hidden and ad-hoc networks. 忽略隐藏的和ad-hoc的网络
if (result.SSID == null || result.SSID.length() == 0 ||
result.capabilities.contains("[IBSS]")) {
continue;
}
//通过ScanResult生成key,形式是ssid/bssid + security
String apKey = AccessPoint.getKey(result);
List<ScanResult> resultList;
if (scanResultsByApKey.containsKey(apKey)) {//已包含同样的key,则获取已有的resultList
resultList = scanResultsByApKey.get(apKey);
} else {
resultList = new ArrayList<>();
scanResultsByApKey.put(apKey, resultList);
}
resultList.add(result);
}
return scanResultsByApKey;
}
BSS
:一种特殊的Ad-hoc LAN的应用,称为Basic Service Set (BSS),一群计算机设定相同的BSS
名称,即可自成一个group,而此BSS名称,即所谓BSSID
。一家公司面积比较大,安装了若干台无线接入点(AP或者无线路由器),公司员工只需要知道一个
SSID
就可以在公司范围内任意地方接入无线网络。BSSID
其实就是每个无线接入点的MAC
地址。当员工在公司内部移动的时候,SSID
是不变的。但BSSID
随着你切换到不同的无线接入点,是在不停变化的。
Ad-hoc
这个词来源于拉丁语,在百度上解释为“for this purpose only”,在wiki上解释为“for this”,其中文在wiki上被解释成包含“特设的、特定目的的(地)、即席的、临时的、将就的、专案的”这么多种含义
ad-hoc
网络实际上可以等价于IBSS(independent BSS)
网络