问题
RK3568 (Android 11),显示已保存的WIFI不会自动重连。
ANDROID 11 新增新特性
背景
多数网络设备在初次连接某个无线网络后会记住密码并在下次自动连接,对多数用户来说这可能是比较好的策略。
毕竟这样不需要用户下次主动查询无线网络再连接,不过苹果倒是很早就在iOS 里提供不自动连接无线网的功能。
即针对特定的无线网络热点可以配置不自动连接,只有用户手动检查时点击连接后系统才会连接到这个网络热点。
在安卓系统中提供类似的功能,可以自己配置哪些网络可以自动连接、哪些网络必须用户确认再连接。来增强安全性
设置
Android 11 及以上版本,用户连接某个热点后点击选项,即可在列表里看到自动连接选项。
如果用户无需自动连接到这个热点的话则关闭自动连接即可,该功能无法批量操作只能挨个对已知热点进行配置。
功能好处
实际上这主要用来规避用户连接公共无线网的。
目前许多大型场所例如商城、餐厅、影院等都提供公共无线网络供用户使用,这类公共无线网络安全性相对较差。
理论上说用户在尝试某些对安全性较高的操作时不应连接这类公共无线网络,因为可能会有被中间人劫持的风险。
当然另一方面现在蜂窝网络和数据流量可能都比较充足,若注重安全的话请直接使用数据流量不要使用公共网络。
自连机制
查看网络状态
显示已保存说明连接的WIFI信息已经保存,Android 11连接的WIFI信息保存在该文件/data/misc/apexdata/com.android.wifi/WifiConfigStore.xml
查看该文件的网络状态选项
show me code
handle 扫描结果 一个回调
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiConnectivityManager.java
private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName,boolean isFullScan) {
mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(
mStateMachine.getWifiLinkLayerStats(), WifiChannelUtilization.UNKNOWN_FREQ);
updateUserDisabledList(scanDetails);
...
localLog(listenerName + " onResults: start network selection");
List<WifiCandidates.Candidate> candidates = mNetworkSelector.getCandidatesFromScan(
scanDetails, bssidBlocklist, mWifiInfo, mStateMachine.isConnected(),
mStateMachine.isDisconnected(), mUntrustedConnectionAllowed);
mLatestCandidates = candidates;
mLatestCandidatesTimestampMs = mClock.getElapsedSinceBootMillis();
....
}
从scan中找出候选 getCandidatesFromScan
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNetworkSelector.java
public List<WifiCandidates.Candidate> getCandidatesFromScan(
List<ScanDetail> scanDetails, Set<String> bssidBlacklist, WifiInfo wifiInfo,
boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) {
mFilteredNetworks.clear();
mConnectableNetworks.clear();
if (scanDetails.size() == 0) {
localLog("Empty connectivity scan result");
return null;
}
WifiConfiguration currentNetwork =
mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());
// Always get the current BSSID from WifiInfo in case that firmware initiated
// roaming happened.
String currentBssid = wifiInfo.getBSSID();
// Update the scan detail cache at the start, even if we skip network selection
updateScanDetailCache(scanDetails);
// Shall we start network selection at all?
if (!isNetworkSelectionNeeded(scanDetails, wifiInfo, connected, disconnected)) {
return null;
}
// Update all configured networks before initiating network selection.
updateConfiguredNetworks();
// Update the registered network nominators.
for (NetworkNominator registeredNominator : mNominators) {
registeredNominator.update(scanDetails);
}
// Filter out unwanted networks.
mFilteredNetworks = filterScanResults(scanDetails, bssidBlacklist,
connected && wifiInfo.getScore() >= WIFI_POOR_SCORE, currentBssid);
if (mFilteredNetworks.size() == 0) {
return null;
}
...
}
isNetworkSelectionNeeded 判断网络选择
private boolean isNetworkSelectionNeeded(List<ScanDetail> scanDetails, WifiInfo wifiInfo,boolean connected, boolean disconnected) {
if (scanDetails.size() == 0) {
localLog("Empty connectivity scan results. Skip network selection.");
return false;
}
if (connected) {
// Is roaming allowed?
if (!mContext.getResources().getBoolean( R.bool.config_wifi_framework_enable_associated_network_selection)) {
localLog("Switching networks in connected state is not allowed."
+ " Skip network selection.");
return false;
}
// Has it been at least the minimum interval since last network selection?
if (mLastNetworkSelectionTimeStamp != INVALID_TIME_STAMP) {
long gap = mClock.getElapsedSinceBootMillis()
- mLastNetworkSelectionTimeStamp;
if (gap < MINIMUM_NETWORK_SELECTION_INTERVAL_MS) {
localLog("Too short since last network selection: " + gap + " ms."
+ " Skip network selection.");
return false;
}
}
// Please note other scans (e.g., location scan or app scan) may also trigger network
// selection and these scans may or may not run sufficiency check.
// So it is better to run sufficiency check here before network selection.
if (isNetworkSufficient(wifiInfo)) {
localLog("Current connected network already sufficient. Skip network selection.");
return false;
} else {
localLog("Current connected network is not sufficient.");
return true;
}
} else if (disconnected) {
return true;
} else {
// No network selection if ClientModeImpl is in a state other than
// CONNECTED or DISCONNECTED.
localLog("ClientModeImpl is in neither CONNECTED nor DISCONNECTED state."
+ " Skip network selection.");
return false;
}
}
workaround 方案
修改默认值 开启:自动连接
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiConnectivityManager.java
private boolean mAutoJoinEnabled = true;