WifiConfigManager
/**
* Helper method to mark a network permanently disabled for network selection.
*/
private void setNetworkSelectionPermanentlyDisabled(
WifiConfiguration config, int disableReason) {
NetworkSelectionStatus status = config.getNetworkSelectionStatus();
status.setNetworkSelectionStatus(
NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED);
status.setDisableTime(
NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
status.setNetworkSelectionDisableReason(disableReason);
if (mListener != null) {
mListener.onSavedNetworkPermanentlyDisabled(config.networkId, disableReason);
}
}
可以看到临时禁用会回调一个listener,看下这个listener是哪里被初始化的
WifiConnectivityManager
@Override
public void onSavedNetworkPermanentlyDisabled(int networkId, int disableReason) {
// For DISABLED_NO_INTERNET_PERMANENT we do not need to remove the network
// because supplicant won't be trying to reconnect. If this is due to a
// preventAutomaticReconnect request from ConnectivityService, that service
// will disconnect as appropriate.
if (disableReason == DISABLED_NO_INTERNET_PERMANENT) return;
mConnectivityHelper.removeNetworkIfCurrent(networkId);
updatePnoScan();
}
这边与临时禁用的区别是会触发一次pno扫描
/**
* Retrieves a list of all the saved networks before enabling disconnected/connected PNO.
*
* PNO network list sent to the firmware has limited size. If there are a lot of saved
* networks, this list will be truncated and we might end up not sending the networks
* with the highest chance of connecting to the firmware.
* So, re-sort the network list based on the frequency of connection to those networks
* and whether it was last seen in the scan results.
*
* @return list of networks in the order of priority.
*/
public List retrievePnoNetworkList() {
List pnoList = new ArrayList<>();
List networks = new ArrayList<>(getInternalConfiguredNetworks());
// Remove any permanently or temporarily disabled networks.
Iterator iter = networks.iterator();
while (iter.hasNext()) {
WifiConfiguration config = iter.next();
if (config.ephemeral || config.isPasspoint()
|| config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()
|| config.getNetworkSelectionStatus().isNetworkTemporaryDisabled()) {
iter.remove();
}
}
这边差个眼,pno扫描的结果是有限制的,只会把最有机会连接的发给firmware
if (mConfig != null && mConfig.hasNoInternetAccess()) {
int messageID = mConfig.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()
? R.string.wifi_no_internet_no_reconnect
: R.string.wifi_no_internet;
summary.append(mContext.getString(messageID));
}
Settings 里的无网络连接的AP会根据是否被禁用而显示不再连接
case CMD_NETWORK_STATUS:
if (message.arg1 == NetworkAgent.VALID_NETWORK) {
// stop collect last-mile stats since validation pass
removeMessages(CMD_DIAGS_CONNECT_TIMEOUT);
mWifiDiagnostics.reportConnectionEvent(
WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED);
mWifiScoreCard.noteValidationSuccess(mWifiInfo);
config = getCurrentWifiConfiguration();
if (config != null) {
// re-enable autojoin
mWifiConfigManager.updateNetworkSelectionStatus(
config.networkId,
WifiConfiguration.NetworkSelectionStatus
.NETWORK_SELECTION_ENABLE);
mWifiConfigManager.setNetworkValidatedInternetAccess(
config.networkId, true);
}
}
break;
网络校验成功的时候会enable
/**
* This API is called when user explicitly selects a network. Currently, it is used in following
* cases:
* (1) User explicitly chooses to connect to a saved network.
* (2) User saves a network after adding a new network.
* (3) User saves a network after modifying a saved network.
* Following actions will be triggered:
* 1. If this network is disabled, we need re-enable it again.
* 2. This network is favored over all the other networks visible in latest network
* selection procedure.
*
* @param netId ID for the network chosen by the user
* @return true -- There is change made to connection choice of any saved network.
* false -- There is no change made to connection choice of any saved network.
*/
public boolean setUserConnectChoice(int netId) {
localLog("userSelectNetwork: network ID=" + netId);
WifiConfiguration selected = mWifiConfigManager.getConfiguredNetwork(netId);
if (selected == null || selected.SSID == null) {
localLog("userSelectNetwork: Invalid configuration with nid=" + netId);
return false;
}
// Enable the network if it is disabled.
if (!selected.getNetworkSelectionStatus().isNetworkEnabled()) {
mWifiConfigManager.updateNetworkSelectionStatus(netId,
WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
}
return setLegacyUserConnectChoice(selected);
}
用户选择的时候会enable,这边另外会干扰自动连接策略,用户选择的优先级最高
/**
* Overrides the {@code candidate} chosen by the {@link #mEvaluators} with the user chosen
* {@link WifiConfiguration} if one exists.
*
* @return the user chosen {@link WifiConfiguration} if one exists, {@code candidate} otherwise
*/
private WifiConfiguration overrideCandidateWithUserConnectChoice(
@NonNull WifiConfiguration candidate) {
WifiConfiguration tempConfig = Preconditions.checkNotNull(candidate);
WifiConfiguration originalCandidate = candidate;
ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate();
while (tempConfig.getNetworkSelectionStatus().getConnectChoice() != null) {
String key = tempConfig.getNetworkSelectionStatus().getConnectChoice();
tempConfig = mWifiConfigManager.getConfiguredNetwork(key);
if (tempConfig != null) {
WifiConfiguration.NetworkSelectionStatus tempStatus =
tempConfig.getNetworkSelectionStatus();
if (tempStatus.getCandidate() != null && tempStatus.isNetworkEnabled()) {
scanResultCandidate = tempStatus.getCandidate();
candidate = tempConfig;
}
} else {
localLog("Connect choice: " + key + " has no corresponding saved config.");
break;
}
}
if (candidate != originalCandidate) {
localLog("After user selection adjustment, the final candidate is:"
+ WifiNetworkSelector.toNetworkString(candidate) + " : "
+ scanResultCandidate.BSSID);
mWifiMetrics.setNominatorForNetwork(candidate.networkId,
WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE);
}
return candidate;
}
/**
* Enable a network using the public {@link WifiManager#enableNetwork(int, boolean)} API.
*
* @param networkId network ID of the network that needs the update.
* @param disableOthers Whether to disable all other networks or not. This is used to indicate
* that the app requested connection to a specific network.
* @param uid uid of the app requesting the update.
* @return true if it succeeds, false otherwise
*/
public boolean enableNetwork(int networkId, boolean disableOthers, int uid) {
if (mVerboseLoggingEnabled) {
Log.v(TAG, "Enabling network " + networkId + " (disableOthers " + disableOthers + ")");
}
if (!doesUidBelongToCurrentUser(uid)) {
Log.e(TAG, "UID " + uid + " not visible to the current user");
return false;
}
WifiConfiguration config = getInternalConfiguredNetwork(networkId);
if (config == null) {
return false;
}
// Set the "last selected" flag even if the app does not have permissions to modify this
// network config. Apps are allowed to connect to networks even if they don't have
// permission to modify it.
if (disableOthers) {
setLastSelectedNetwork(networkId);
}
if (!canModifyNetwork(config, uid)) {
Log.e(TAG, "UID " + uid + " does not have permission to update configuration "
+ config.configKey());
return false;
}
if (!updateNetworkSelectionStatus(
networkId, WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE)) {
return false;
}
saveToStore(true);
return true;
}
这边会由ClientModeImpl显示调用保存、enable或者连接的时候走到,这边其实包含了3.1和3.2