fix handling DHCP status
Change-Id: Ib4dfc9a1f84d6faaaf71adf63c8e2457e95646fd
diff --git a/service/java/com/android/server/wifi/WifiAutoJoinController.java b/service/java/com/android/server/wifi/WifiAutoJoinController.java
index b01994c..d97a161 100644
--- a/service/java/com/android/server/wifi/WifiAutoJoinController.java
+++ b/service/java/com/android/server/wifi/WifiAutoJoinController.java
@@ -67,6 +67,9 @@
/* for debug purpose only : the untrusted SSID we would be connected to if we had VPN */
String lastUntrustedBSSID = null;
+ /* For debug purpose only: if the scored override a score */
+ boolean didOverride = false;
+
// Lose the non-auth failure blacklisting after 8 hours
private final static long loseBlackListHardMilli = 1000 * 60 * 60 * 8;
// Lose some temporary blacklisting after 30 minutes
@@ -274,6 +277,8 @@
WifiConfiguration currentNetwork = mWifiStateMachine.getCurrentWifiConfiguration();
if (currentNetwork == null) {
+ // Return any absurdly high score, if we are not connected there is no current
+ // network to...
return 1000;
}
@@ -281,7 +286,7 @@
return -2;
}
- int order = compareWifiConfigurations(currentNetwork, candidate);
+ int order = compareWifiConfigurationsTop(currentNetwork, candidate);
return order;
}
@@ -525,9 +530,9 @@
// Apply Hysteresis, boost RSSI of current configuration
if (null != currentConfiguration) {
if (a.configKey().equals(currentConfiguration)) {
- aRssiBoost += 15;
+ aRssiBoost += 20;
} else if (b.configKey().equals(currentConfiguration)) {
- bRssiBoost += 15;
+ bRssiBoost += 20;
}
}
@@ -588,9 +593,9 @@
// looking up the score
if (null != mCurrentConfigurationKey) {
if (a.configKey().equals(mCurrentConfigurationKey)) {
- aRssiBoost += 15;
+ aRssiBoost += 20;
} else if (b.configKey().equals(mCurrentConfigurationKey)) {
- bRssiBoost += 15;
+ bRssiBoost += 20;
}
}
int scoreA = getConfigNetworkScore(a, 3000, aRssiBoost);
@@ -728,9 +733,29 @@
return (rssi5 < -80 && rssi24 < -90);
}
- /**
- * attemptRoam function implements the core of the same SSID switching algorithm
- */
+ int compareWifiConfigurationsTop(WifiConfiguration a, WifiConfiguration b) {
+ int scorerOrder = compareWifiConfigurationsWithScorer(a, b);
+ int order = compareWifiConfigurations(a, b);
+
+ if (scorerOrder * order < 0) {
+ // For debugging purpose, remember that an override happened
+ // during that autojoin Attempt
+ didOverride = true;
+ a.numScorerOverride++;
+ b.numScorerOverride++;
+ }
+
+ if (scorerOrder != 0) {
+ // If the scorer came up with a result then use the scorer's result, else use
+ // the order provided by the base comparison function
+ order = scorerOrder;
+ }
+ return order;
+ }
+
+ /**
+ * attemptRoam function implements the core of the same SSID switching algorithm
+ */
ScanResult attemptRoam(WifiConfiguration current, int age) {
ScanResult a = null;
if (current == null) {
@@ -871,6 +896,7 @@
*
* @param config
* @return score
+ * @return score
*/
int getConfigNetworkScore(WifiConfiguration config, int age, int rssiBoost) {
@@ -898,7 +924,7 @@
* attemptAutoJoin() function implements the core of the a network switching algorithm
*/
void attemptAutoJoin() {
- boolean didOverride = false;
+ didOverride = false;
int networkSwitchType = AUTO_JOIN_IDLE;
String lastSelectedConfiguration = mWifiConfigStore.getLastSelectedConfiguration();
@@ -1083,8 +1109,8 @@
if (lastSelectedConfiguration == null ||
!config.configKey().equals(lastSelectedConfiguration)) {
- // Don't try to autojoin a network that is too far
- // If that configuration is
+ // Don't try to autojoin a network that is too far but
+ // If that configuration is a user's choice however, try anyway
if (config.visibility == null) {
continue;
}
@@ -1117,26 +1143,10 @@
logDbg("attemptAutoJoin will compare candidate " + candidate.configKey()
+ " with " + config.configKey());
}
-
- int scorerOrder = compareWifiConfigurationsWithScorer(candidate, config);
- int order = compareWifiConfigurations(candidate, config);
-
- if (scorerOrder * order < 0) {
- // For debugging purpose, remember that an override happened
- // during that autojoin Attempt
- didOverride = true;
- candidate.numScorerOverride++;
- config.numScorerOverride++;
- }
-
- if (scorerOrder != 0) {
- // If the scorer came up with a result then use the scorer's result, else use
- // the order provided by the base comparison function
- order = scorerOrder;
- }
+ int order = compareWifiConfigurationsTop(candidate, config);
// The lastSelectedConfiguration is the configuration the user has manually selected
- // thru thru WifiPicker, or that a 3rd party app asked us to connect to via the
+ // thru WifiPicker, or that a 3rd party app asked us to connect to via the
// enableNetwork with disableOthers=true WifiManager API
// As this is a direct user choice, we strongly prefer this configuration,
// hence give +/-100
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index 69808a0..97aad0f 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -44,6 +44,7 @@
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyChain;
import android.security.KeyStore;
@@ -222,6 +223,18 @@
WifiEnterpriseConfig.ENGINE_KEY, WifiEnterpriseConfig.ENGINE_ID_KEY,
WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY };
+
+ /**
+ * The maximum number of times we will retry a connection to an access point
+ * for which we have failed in acquiring an IP address from DHCP. A value of
+ * N means that we will make N+1 connection attempts in all.
+ * <p>
+ * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default
+ * value if a Settings value is not present.
+ */
+ private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
+
+
private final LocalLog mLocalLog;
private final WpaConfigFileObserver mFileObserver;
@@ -390,7 +403,7 @@
result.averageRssi(previousRssi, previousSeen,
WifiAutoJoinController.mScanResultMaximumAge);
if (VDBG) {
- loge("updateConfiguration freq=" + result.level
+ loge("updateConfiguration freq=" + result.frequency
+ " BSSID=" + result.BSSID
+ " RSSI=" + result.level
+ " " + config.configKey());
@@ -2820,6 +2833,12 @@
return found;
}
+ int getMaxDhcpRetries() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
+ DEFAULT_MAX_DHCP_RETRIES);
+ }
+
void handleSSIDStateChange(int netId, boolean enabled, String message) {
WifiConfiguration config = mConfiguredNetworks.get(netId);
if (config != null) {
@@ -2880,6 +2899,25 @@
loge("blacklisted " + config.configKey() + " to "
+ Integer.toString(config.autoJoinStatus));
}
+ } else if (message.contains("DHCP FAILURE")) {
+ config.numConnectionFailures++;
+ config.lastConnectionFailure = System.currentTimeMillis();
+ int maxRetries = getMaxDhcpRetries();
+ // maxRetries == 0 means keep trying forever
+ if (maxRetries > 0 && config.numConnectionFailures > maxRetries) {
+ /**
+ * If we've exceeded the maximum number of retries for DHCP
+ * to a given network, disable the network
+ */
+ config.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE);
+ disableNetwork(netId, WifiConfiguration.DISABLED_DHCP_FAILURE);
+ }
+ if (DBG) {
+ loge("blacklisted " + config.configKey() + " to "
+ + config.autoJoinStatus
+ + " due to DHCP failure, count="
+ + config.numConnectionFailures);
+ }
}
message.replace("\n", "");
message.replace("\r", "");
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 2a97b98..21b7bc9 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -185,7 +185,6 @@
private boolean mEnableRssiPolling = false;
private boolean mEnableBackgroundScan = false;
private int mRssiPollToken = 0;
- private int mReconnectCount = 0;
/* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE
* In CONNECT_MODE, the STA can scan and connect to an access point
* In SCAN_ONLY_MODE, the STA can only scan for access points
@@ -523,16 +522,6 @@
private static final int SUCCESS = 1;
private static final int FAILURE = -1;
- /**
- * The maximum number of times we will retry a connection to an access point
- * for which we have failed in acquiring an IP address from DHCP. A value of
- * N means that we will make N+1 connection attempts in all.
- * <p>
- * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default
- * value if a Settings value is not present.
- */
- private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
-
/* Tracks if suspend optimizations need to be disabled by DHCP,
* screen or due to high perf mode.
* When any of them needs to disable it, we keep the suspend optimizations
@@ -2053,7 +2042,6 @@
pw.println("mLastSignalLevel " + mLastSignalLevel);
pw.println("mLastBssid " + mLastBssid);
pw.println("mLastNetworkId " + mLastNetworkId);
- pw.println("mReconnectCount " + mReconnectCount);
pw.println("mOperationalMode " + mOperationalMode);
pw.println("mUserWantsSuspendOpt " + mUserWantsSuspendOpt);
pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
@@ -2285,6 +2273,19 @@
}
}
break;
+ case CMD_IP_CONFIGURATION_LOST:
+ int count = -1;
+ WifiConfiguration c = getCurrentWifiConfiguration();
+ if (c != null) count = c.numConnectionFailures;
+ sb.append(" ");
+ sb.append(Integer.toString(msg.arg1));
+ sb.append(" ");
+ sb.append(Integer.toString(msg.arg2));
+ sb.append(" failures: ");
+ sb.append(Integer.toString(count));
+ sb.append("/");
+ sb.append(Integer.toString(mWifiConfigStore.getMaxDhcpRetries()));
+ break;
default:
sb.append(" ");
sb.append(Integer.toString(msg.arg1));
@@ -3001,7 +3002,7 @@
* - IPv6 routes and DNS servers: netlink, passed in by mNetlinkTracker.
* - HTTP proxy: the wifi config store.
*/
- private void updateLinkProperties() {
+ private void updateLinkProperties(boolean failure) {
LinkProperties newLp = new LinkProperties();
// Interface name and proxy are locally configured.
@@ -3048,6 +3049,38 @@
if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties);
}
+ if (DBG) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("updateLinkProperties nid: " + mLastNetworkId);
+ sb.append(" state: " + detailedState);
+ if (failure) sb.append(" failure");
+
+ if (mLinkProperties != null) {
+ if (mLinkProperties.hasIPv4Address()) {
+ sb.append(" v4");
+ }
+ if (mLinkProperties.hasGlobalIPv6Address()) {
+ sb.append(" v6");
+ }
+ if (mLinkProperties.hasIPv4DefaultRoute()) {
+ sb.append(" v4r");
+ }
+ if (mLinkProperties.hasIPv6DefaultRoute()) {
+ sb.append(" v6r");
+ }
+ if (mLinkProperties.hasIPv4DnsServer()) {
+ sb.append(" v4dns");
+ }
+ if (mLinkProperties.hasIPv6DnsServer()) {
+ sb.append(" v6dns");
+ }
+ if (mLinkProperties.isProvisioned()) {
+ sb.append(" isprov");
+ }
+ }
+ loge(sb.toString());
+ }
+
// If we just configured or lost IP configuration, do the needful.
// We don't just call handleSuccessfulIpConfiguration() or handleIpConfigurationLost()
// here because those should only be called if we're attempting to connect or already
@@ -3055,10 +3088,10 @@
// Also, when roaming we don't pass through a not-provisioned state but
// still need to realize we have an IP_CONFIGURATION_SUCCESSFUL.
if (isProvisioned &&
- (!wasProvisioned || detailedState == DetailedState.OBTAINING_IPADDR)) {
+ (!wasProvisioned || getCurrentState() == mObtainingIpState)) {
sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL);
} else if (!isProvisioned && (wasProvisioned
- || detailedState == DetailedState.OBTAINING_IPADDR)) {
+ || failure && getCurrentState() == mObtainingIpState)) {
sendMessage(CMD_IP_CONFIGURATION_LOST);
} else if (linkChanged && getNetworkDetailedState() == DetailedState.CONNECTED) {
// If anything has changed, and we're already connected, send out a notification.
@@ -3134,12 +3167,6 @@
return address;
}
- private int getMaxDhcpRetries() {
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
- DEFAULT_MAX_DHCP_RETRIES);
- }
-
private void sendScanResultsAvailableBroadcast() {
noteScanEnd();
Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
@@ -3387,7 +3414,7 @@
private void handleIPv4Success(DhcpResults dhcpResults) {
if (PDBG) {
- loge("handleIPv4Success <" + dhcpResults.toString()
+ loge("wifistatemachine handleIPv4Success <" + dhcpResults.toString()
+ "> linkaddress num " + dhcpResults.linkProperties.getLinkAddresses().size());
for (LinkAddress linkAddress : dhcpResults.linkProperties.getLinkAddresses()) {
loge("link address " + linkAddress.toString());
@@ -3424,12 +3451,16 @@
}
mWifiInfo.setInetAddress(addr);
mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint());
- updateLinkProperties();
+ updateLinkProperties(false);
}
private void handleSuccessfulIpConfiguration() {
mLastSignalLevel = -1; // Force update of signal strength
- mReconnectCount = 0; // Reset IP failure tracking
+ WifiConfiguration c = getCurrentWifiConfiguration();
+ // Reset IP failure tracking
+ if (c != null) {
+ c.numConnectionFailures = 0;
+ }
}
private void handleIPv4Failure() {
@@ -3438,31 +3469,22 @@
mDhcpResults.linkProperties.clear();
}
}
- updateLinkProperties();
+ if (PDBG) {
+ loge("wifistatemachine handleIPv4Failure");
+ }
+ updateLinkProperties(true);
}
private void handleIpConfigurationLost() {
mWifiInfo.setInetAddress(null);
mWifiInfo.setMeteredHint(false);
- /**
- * If we've exceeded the maximum number of retries for DHCP
- * to a given network, disable the network
- */
- int maxRetries = getMaxDhcpRetries();
- // maxRetries == 0 means keep trying forever
- if (maxRetries > 0 && ++mReconnectCount > maxRetries) {
- loge("Failed " +
- mReconnectCount + " times, Disabling " + mLastNetworkId);
- mWifiConfigStore.disableNetwork(mLastNetworkId,
- WifiConfiguration.DISABLED_DHCP_FAILURE);
- mReconnectCount = 0;
- }
+
+ mWifiConfigStore.handleSSIDStateChange(mLastNetworkId, false, "DHCP FAILURE");
/* DHCP times out after about 30 seconds, we do a
- * disconnect and an immediate reconnect to try again
+ * disconnect thru supplicant, we will let autojoin retry connecting to the network
*/
mWifiNative.disconnect();
- mWifiNative.reconnect();
}
/* Current design is to not set the config on a running hostapd but instead
@@ -3758,7 +3780,7 @@
break;
/* Link configuration (IP address, DNS, ...) changes notified via netlink */
case CMD_NETLINK_UPDATE:
- updateLinkProperties();
+ updateLinkProperties(false);
break;
case CMD_IP_CONFIGURATION_SUCCESSFUL:
case CMD_IP_CONFIGURATION_LOST:
@@ -4881,6 +4903,12 @@
case WifiManager.WPS_COMPLETED:
s = "WPS_COMPLETED";
break;
+ case CMD_IP_CONFIGURATION_LOST:
+ s = "CMD_IP_CONFIGURATION_LOST";
+ break;
+ case CMD_IP_CONFIGURATION_SUCCESSFUL:
+ s = "CMD_IP_CONFIGURATION_SUCCESSFUL";
+ break;
default:
s = "what:" + Integer.toString(message.what);
break;
@@ -5375,7 +5403,7 @@
public void exit() {
// This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState
// Bug: 15347363
- // For paranoia's sake, call handleNEtworkDisconnect only if BSSID is null or last networkId
+ // For paranoia's sake, call handleNetworkDisconnect only if BSSID is null or last networkId
// is not invalid.
if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
handleNetworkDisconnect();
@@ -5393,12 +5421,19 @@
case DhcpStateMachine.CMD_POST_DHCP_ACTION:
handlePostDhcpSetup();
if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) {
- if (DBG) log("DHCP successful");
+ if (DBG) log("WifiStateMachine DHCP successful");
handleIPv4Success((DhcpResults) message.obj);
// We advance to mVerifyingLinkState because handleIPv4Success will call
// updateLinkProperties, which then sends CMD_IP_CONFIGURATION_SUCCESSFUL.
} else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) {
- if (DBG) log("DHCP failed");
+ if (DBG) {
+ int count = -1;
+ WifiConfiguration config = getCurrentWifiConfiguration();
+ if (config != null) {
+ count = config.numConnectionFailures;
+ }
+ log("WifiStateMachine DHCP failure count=" + count);
+ }
handleIPv4Failure();
// As above, we transition to mDisconnectingState via updateLinkProperties.
}
@@ -5563,7 +5598,7 @@
}
if (result.hasProxyChanged()) {
log("Reconfiguring proxy on connection");
- updateLinkProperties();
+ updateLinkProperties(false);
}
}