diff options
-rw-r--r-- | service/java/com/android/server/wifi/WifiAutoJoinController.java | 59 | ||||
-rw-r--r-- | service/java/com/android/server/wifi/WifiNetworkScoreCache.java | 74 |
2 files changed, 96 insertions, 37 deletions
diff --git a/service/java/com/android/server/wifi/WifiAutoJoinController.java b/service/java/com/android/server/wifi/WifiAutoJoinController.java index e30b1c789..d2ae76a43 100644 --- a/service/java/com/android/server/wifi/WifiAutoJoinController.java +++ b/service/java/com/android/server/wifi/WifiAutoJoinController.java @@ -22,6 +22,8 @@ import android.net.NetworkScoreManager; import android.net.WifiKey; import android.net.wifi.*; import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.os.SystemClock; +import android.provider.Settings; import android.text.TextUtils; import android.util.Log; @@ -75,6 +77,9 @@ public class WifiAutoJoinController { // Lose some temporary blacklisting after 30 minutes private final static long loseBlackListSoftMilli = 1000 * 60 * 30; + /** @see android.provider.Settings.Global#WIFI_EPHEMERAL_OUT_OF_RANGE_TIMEOUT_MS */ + private static final long DEFAULT_EPHEMERAL_OUT_OF_RANGE_TIMEOUT_MS = 1000 * 60; // 1 minute + public static final int AUTO_JOIN_IDLE = 0; public static final int AUTO_JOIN_ROAMING = 1; public static final int AUTO_JOIN_EXTENDED_ROAMING = 2; @@ -1169,6 +1174,53 @@ public class WifiAutoJoinController { !result.capabilities.contains("EAP"); } + private boolean haveRecentlySeenScoredBssid(WifiConfiguration config) { + long ephemeralOutOfRangeTimeoutMs = Settings.Global.getLong( + mContext.getContentResolver(), + Settings.Global.WIFI_EPHEMERAL_OUT_OF_RANGE_TIMEOUT_MS, + DEFAULT_EPHEMERAL_OUT_OF_RANGE_TIMEOUT_MS); + + // Check whether the currently selected network has a score curve. If + // ephemeralOutOfRangeTimeoutMs is <= 0, then this is all we check, and we stop here. + // Otherwise, we stop here if the currently selected network has a score. If it doesn't, we + // keep going - it could be that another BSSID is in range (has been seen recently) which + // has a score, even if the one we're immediately connected to doesn't. + ScanResult currentScanResult = mWifiStateMachine.getCurrentScanResult(); + boolean currentNetworkHasScoreCurve = mNetworkScoreCache.hasScoreCurve(currentScanResult); + if (ephemeralOutOfRangeTimeoutMs <= 0 || currentNetworkHasScoreCurve) { + if (DBG) { + if (currentNetworkHasScoreCurve) { + logDbg("Current network has a score curve, keeping network: " + + currentScanResult); + } else { + logDbg("Current network has no score curve, giving up: " + config.SSID); + } + } + return currentNetworkHasScoreCurve; + } + + if (config.scanResultCache == null || config.scanResultCache.isEmpty()) { + return false; + } + + long currentTimeMs = System.currentTimeMillis(); + for (ScanResult result : config.scanResultCache.values()) { + if (currentTimeMs > result.seen + && currentTimeMs - result.seen < ephemeralOutOfRangeTimeoutMs + && mNetworkScoreCache.hasScoreCurve(result)) { + if (DBG) { + logDbg("Found scored BSSID, keeping network: " + result.BSSID); + } + return true; + } + } + + if (DBG) { + logDbg("No recently scored BSSID found, giving up connection: " + config.SSID); + } + return false; + } + /** * attemptAutoJoin() function implements the core of the a network switching algorithm * Return false if no acceptable networks were found. @@ -1277,10 +1329,11 @@ public class WifiAutoJoinController { mWifiStateMachine.disconnectCommand(); return false; } else if (currentConfiguration.ephemeral && (!mAllowUntrustedConnections || - !mNetworkScoreCache.isScoredNetwork(currentConfiguration.lastSeen()))) { + !haveRecentlySeenScoredBssid(currentConfiguration))) { // The current connection is untrusted (the framework added it), but we're either - // no longer allowed to connect to such networks, or the score has been nullified - // since we connected. Drop the current connection and perform the rest of autojoin. + // no longer allowed to connect to such networks, the score has been nullified + // since we connected, or the scored BSSID has gone out of range. + // Drop the current connection and perform the rest of autojoin. logDbg("attemptAutoJoin() disconnecting from unwanted ephemeral network"); mWifiStateMachine.disconnectCommand(); return false; diff --git a/service/java/com/android/server/wifi/WifiNetworkScoreCache.java b/service/java/com/android/server/wifi/WifiNetworkScoreCache.java index 0a6852788..0a7df0b0e 100644 --- a/service/java/com/android/server/wifi/WifiNetworkScoreCache.java +++ b/service/java/com/android/server/wifi/WifiNetworkScoreCache.java @@ -73,37 +73,38 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub } } + /** + * Returns whether there is any score info for the given ScanResult. + * + * This includes null-score info, so it should only be used when determining whether to request + * scores from the network scorer. + */ public boolean isScoredNetwork(ScanResult result) { - String key = buildNetworkKey(result); - if (key == null) return false; + return getScoredNetwork(result) != null; + } - //find it - synchronized(mNetworkCache) { - ScoredNetwork network = mNetworkCache.get(key); - if (network != null) { - return true; - } - } - return false; + /** + * Returns whether there is a non-null score curve for the given ScanResult. + * + * A null score curve has special meaning - we should never connect to an ephemeral network if + * the score curve is null. + */ + public boolean hasScoreCurve(ScanResult result) { + ScoredNetwork network = getScoredNetwork(result); + return network != null && network.rssiCurve != null; } public int getNetworkScore(ScanResult result) { int score = INVALID_NETWORK_SCORE; - String key = buildNetworkKey(result); - if (key == null) return score; - - //find it - synchronized(mNetworkCache) { - ScoredNetwork network = mNetworkCache.get(key); - if (network != null && network.rssiCurve != null) { - score = network.rssiCurve.lookupScore(result.level); - if (DBG) { - Log.e(TAG, "getNetworkScore found scored network " + key - + " score " + Integer.toString(score) - + " RSSI " + result.level); - } + ScoredNetwork network = getScoredNetwork(result); + if (network != null && network.rssiCurve != null) { + score = network.rssiCurve.lookupScore(result.level); + if (DBG) { + Log.e(TAG, "getNetworkScore found scored network " + network.networkKey + + " score " + Integer.toString(score) + + " RSSI " + result.level); } } return score; @@ -113,23 +114,28 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub int score = INVALID_NETWORK_SCORE; + ScoredNetwork network = getScoredNetwork(result); + if (network != null && network.rssiCurve != null) { + score = network.rssiCurve.lookupScore(result.level, isActiveNetwork); + if (DBG) { + Log.e(TAG, "getNetworkScore found scored network " + network.networkKey + + " score " + Integer.toString(score) + + " RSSI " + result.level + + " isActiveNetwork " + isActiveNetwork); + } + } + return score; + } + + private ScoredNetwork getScoredNetwork(ScanResult result) { String key = buildNetworkKey(result); - if (key == null) return score; + if (key == null) return null; //find it synchronized(mNetworkCache) { ScoredNetwork network = mNetworkCache.get(key); - if (network != null && network.rssiCurve != null) { - score = network.rssiCurve.lookupScore(result.level, isActiveNetwork); - if (DBG) { - Log.e(TAG, "getNetworkScore found scored network " + key - + " score " + Integer.toString(score) - + " RSSI " + result.level - + " isActiveNetwork " + isActiveNetwork); - } - } + return network; } - return score; } private String buildNetworkKey(ScoredNetwork network) { |