diff options
author | Irfan Sheriff <isheriff@google.com> | 2012-03-08 16:11:02 -0800 |
---|---|---|
committer | Irfan Sheriff <isheriff@google.com> | 2012-03-08 16:28:35 -0800 |
commit | 4c8982ad820007512e4e9cbb7f15925228d70761 (patch) | |
tree | f9248bab5afea0c3b09d49a86a141747588ddd64 /wifi/java/android/net | |
parent | b7fdddab0d1cfa666747a0295fcea4bfea709737 (diff) | |
download | frameworks_base-4c8982ad820007512e4e9cbb7f15925228d70761.zip frameworks_base-4c8982ad820007512e4e9cbb7f15925228d70761.tar.gz frameworks_base-4c8982ad820007512e4e9cbb7f15925228d70761.tar.bz2 |
Enhancements for avoiding poor connection on wifi
- Avoid flapping
- Increase thresholds and monitor rssi more closely to detect consistently weak signal
Change-Id: I6139a20b7306839b345146a72ce690020a2e00b8
Diffstat (limited to 'wifi/java/android/net')
-rw-r--r-- | wifi/java/android/net/wifi/WifiStateMachine.java | 9 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/WifiWatchdogStateMachine.java | 180 |
2 files changed, 150 insertions, 39 deletions
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 843620c..05a8ca7 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -1852,6 +1852,9 @@ public class WifiStateMachine extends StateMachine { replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, WifiManager.BUSY); break; + case WifiWatchdogStateMachine.RSSI_FETCH: + replyToMessage(message, WifiWatchdogStateMachine.RSSI_FETCH_FAILED); + break; default: loge("Error! unhandled message" + message); break; @@ -2998,6 +3001,12 @@ public class WifiStateMachine extends StateMachine { mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); } break; + case WifiWatchdogStateMachine.RSSI_FETCH: + eventLoggingEnabled = false; + fetchRssiAndLinkSpeedNative(); + replyToMessage(message, WifiWatchdogStateMachine.RSSI_FETCH_SUCCEEDED, + mWifiInfo.getRssi()); + break; default: return NOT_HANDLED; } diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java index a2f6343..5c9bef9 100644 --- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java +++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java @@ -93,17 +93,36 @@ public class WifiWatchdogStateMachine extends StateMachine { private static final String TAG = "WifiWatchdogStateMachine"; private static final String WALLED_GARDEN_NOTIFICATION_ID = "WifiWatchdog.walledgarden"; + /* RSSI Levels as used by notification icon + Level 4 -55 <= RSSI + Level 3 -66 <= RSSI < -55 + Level 2 -77 <= RSSI < -67 + Level 1 -88 <= RSSI < -78 + Level 0 RSSI < -88 */ + /* Wi-fi connection is considered poor below this RSSI level threshold and the watchdog report it to the WifiStateMachine */ - private static final int RSSI_LEVEL_CUTOFF = 1; + private static final int RSSI_LEVEL_CUTOFF = 0; /* Wi-fi connection is monitored actively below this threshold */ - private static final int RSSI_LEVEL_MONITOR = 2; + private static final int RSSI_LEVEL_MONITOR = 1; + /* RSSI threshold during monitoring below which network is avoided */ + private static final int RSSI_MONITOR_THRESHOLD = -84; + /* Number of times RSSI is measured to be low before being avoided */ + private static final int RSSI_MONITOR_COUNT = 5; + private int mRssiMonitorCount = 0; + + /* Avoid flapping */ + private static final int MIN_INTERVAL_AVOID_BSSID_MS = 60 * 1000; + private String mLastAvoidedBssid; + /* a -ve interval to allow avoidance at boot */ + private long mLastBssidAvoidedTime = -MIN_INTERVAL_AVOID_BSSID_MS; private int mCurrentSignalLevel; private static final long DEFAULT_ARP_CHECK_INTERVAL_MS = 2 * 60 * 1000; + private static final long DEFAULT_RSSI_FETCH_INTERVAL_MS = 1000; private static final long DEFAULT_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000; private static final int DEFAULT_NUM_ARP_PINGS = 5; @@ -143,10 +162,14 @@ public class WifiWatchdogStateMachine extends StateMachine { /* Internal messages */ private static final int CMD_ARP_CHECK = BASE + 11; private static final int CMD_DELAYED_WALLED_GARDEN_CHECK = BASE + 12; + private static final int CMD_RSSI_FETCH = BASE + 13; /* Notifications to WifiStateMachine */ static final int POOR_LINK_DETECTED = BASE + 21; static final int GOOD_LINK_DETECTED = BASE + 22; + static final int RSSI_FETCH = BASE + 23; + static final int RSSI_FETCH_SUCCEEDED = BASE + 24; + static final int RSSI_FETCH_FAILED = BASE + 25; private static final int SINGLE_ARP_CHECK = 0; private static final int FULL_ARP_CHECK = 1; @@ -167,11 +190,15 @@ public class WifiWatchdogStateMachine extends StateMachine { private WalledGardenCheckState mWalledGardenCheckState = new WalledGardenCheckState(); /* Online and watching link connectivity */ private OnlineWatchState mOnlineWatchState = new OnlineWatchState(); + /* RSSI level is at RSSI_LEVEL_MONITOR and needs close monitoring */ + private RssiMonitoringState mRssiMonitoringState = new RssiMonitoringState(); /* Online and doing nothing */ private OnlineState mOnlineState = new OnlineState(); private int mArpToken = 0; private long mArpCheckIntervalMs; + private int mRssiFetchToken = 0; + private long mRssiFetchIntervalMs; private long mWalledGardenIntervalMs; private int mNumArpPings; private int mMinArpResponses; @@ -219,6 +246,7 @@ public class WifiWatchdogStateMachine extends StateMachine { addState(mConnectedState, mWatchdogEnabledState); addState(mWalledGardenCheckState, mConnectedState); addState(mOnlineWatchState, mConnectedState); + addState(mRssiMonitoringState, mOnlineWatchState); addState(mOnlineState, mConnectedState); if (isWatchdogEnabled()) { @@ -239,6 +267,7 @@ public class WifiWatchdogStateMachine extends StateMachine { // Disable for wifi only devices. if (Settings.Secure.getString(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON) == null && sWifiOnly) { + log("Disabling watchog for wi-fi only device"); putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, false); } WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context); @@ -361,6 +390,7 @@ public class WifiWatchdogStateMachine extends StateMachine { pw.println("mLinkProperties: [" + mLinkProperties + "]"); pw.println("mCurrentSignalLevel: [" + mCurrentSignalLevel + "]"); pw.println("mArpCheckIntervalMs: [" + mArpCheckIntervalMs+ "]"); + pw.println("mRssiFetchIntervalMs: [" + mRssiFetchIntervalMs + "]"); pw.println("mWalledGardenIntervalMs: [" + mWalledGardenIntervalMs + "]"); pw.println("mNumArpPings: [" + mNumArpPings + "]"); pw.println("mMinArpResponses: [" + mMinArpResponses + "]"); @@ -371,7 +401,9 @@ public class WifiWatchdogStateMachine extends StateMachine { } private boolean isWatchdogEnabled() { - return getSettingsBoolean(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true); + boolean ret = getSettingsBoolean(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true); + if (DBG) log("watchdog enabled " + ret); + return ret; } private void updateSettings() { @@ -380,6 +412,9 @@ public class WifiWatchdogStateMachine extends StateMachine { mArpCheckIntervalMs = Secure.getLong(mContentResolver, Secure.WIFI_WATCHDOG_ARP_CHECK_INTERVAL_MS, DEFAULT_ARP_CHECK_INTERVAL_MS); + mRssiFetchIntervalMs = Secure.getLong(mContentResolver, + Secure.WIFI_WATCHDOG_RSSI_FETCH_INTERVAL_MS, + DEFAULT_RSSI_FETCH_INTERVAL_MS); mNumArpPings = Secure.getInt(mContentResolver, Secure.WIFI_WATCHDOG_NUM_ARP_PINGS, DEFAULT_NUM_ARP_PINGS); @@ -436,6 +471,11 @@ public class WifiWatchdogStateMachine extends StateMachine { class DefaultState extends State { @Override + public void enter() { + if (DBG) log(getName() + "\n"); + } + + @Override public boolean processMessage(Message msg) { switch (msg.what) { case EVENT_WATCHDOG_SETTINGS_CHANGE: @@ -445,13 +485,15 @@ public class WifiWatchdogStateMachine extends StateMachine { } break; case EVENT_RSSI_CHANGE: - mCurrentSignalLevel = WifiManager.calculateSignalLevel(msg.arg1, - WifiManager.RSSI_LEVELS); + mCurrentSignalLevel = calculateSignalLevel(msg.arg1); break; case EVENT_WIFI_RADIO_STATE_CHANGE: case EVENT_NETWORK_STATE_CHANGE: case CMD_ARP_CHECK: case CMD_DELAYED_WALLED_GARDEN_CHECK: + case CMD_RSSI_FETCH: + case RSSI_FETCH_SUCCEEDED: + case RSSI_FETCH_FAILED: //ignore break; default: @@ -464,6 +506,11 @@ public class WifiWatchdogStateMachine extends StateMachine { class WatchdogDisabledState extends State { @Override + public void enter() { + if (DBG) log(getName() + "\n"); + } + + @Override public boolean processMessage(Message msg) { switch (msg.what) { case EVENT_WATCHDOG_TOGGLED: @@ -493,7 +540,7 @@ public class WifiWatchdogStateMachine extends StateMachine { @Override public void enter() { if (DBG) log("WifiWatchdogService enabled"); - } + } @Override public boolean processMessage(Message msg) { @@ -507,6 +554,8 @@ public class WifiWatchdogStateMachine extends StateMachine { NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); + if (DBG) log("network state change " + networkInfo.getDetailedState()); + switch (networkInfo.getDetailedState()) { case VERIFYING_POOR_LINK: mLinkProperties = (LinkProperties) intent.getParcelableExtra( @@ -557,6 +606,10 @@ public class WifiWatchdogStateMachine extends StateMachine { } class NotConnectedState extends State { + @Override + public void enter() { + if (DBG) log(getName() + "\n"); + } } class VerifyingLinkState extends State { @@ -568,7 +621,7 @@ public class WifiWatchdogStateMachine extends StateMachine { } private void handleRssiChange() { - if (mCurrentSignalLevel <= RSSI_LEVEL_CUTOFF) { + if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) { //stay here if (DBG) log("enter VerifyingLinkState, stay level: " + mCurrentSignalLevel); } else { @@ -587,11 +640,7 @@ public class WifiWatchdogStateMachine extends StateMachine { } break; case EVENT_RSSI_CHANGE: - int signalLevel = WifiManager.calculateSignalLevel(msg.arg1, - WifiManager.RSSI_LEVELS); - if (DBG) log("RSSI change old: " + mCurrentSignalLevel + "new: " + signalLevel); - mCurrentSignalLevel = signalLevel; - + mCurrentSignalLevel = calculateSignalLevel(msg.arg1); handleRssiChange(); break; case CMD_ARP_CHECK: @@ -680,11 +729,11 @@ public class WifiWatchdogStateMachine extends StateMachine { private void handleRssiChange() { if (mCurrentSignalLevel <= RSSI_LEVEL_CUTOFF) { - if (DBG) log("Transition out, below cut off level: " + mCurrentSignalLevel); - mWsmChannel.sendMessage(POOR_LINK_DETECTED); + sendPoorLinkDetected(); } else if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) { - if (DBG) log("Start monitoring, level: " + mCurrentSignalLevel); - sendMessage(obtainMessage(CMD_ARP_CHECK, ++mArpToken, 0)); + transitionTo(mRssiMonitoringState); + } else { + //stay here } } @@ -692,43 +741,82 @@ public class WifiWatchdogStateMachine extends StateMachine { public boolean processMessage(Message msg) { switch (msg.what) { case EVENT_RSSI_CHANGE: - int signalLevel = WifiManager.calculateSignalLevel(msg.arg1, - WifiManager.RSSI_LEVELS); - if (DBG) log("RSSI change old: " + mCurrentSignalLevel + "new: " + signalLevel); - mCurrentSignalLevel = signalLevel; + mCurrentSignalLevel = calculateSignalLevel(msg.arg1); + //Ready to avoid bssid again ? + long time = android.os.SystemClock.elapsedRealtime(); + if (time - mLastBssidAvoidedTime > MIN_INTERVAL_AVOID_BSSID_MS) { + handleRssiChange(); + } else { + if (DBG) log("Early to avoid " + mWifiInfo + " time: " + time + + " last avoided: " + mLastBssidAvoidedTime); + } + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } - handleRssiChange(); + class RssiMonitoringState extends State { + public void enter() { + if (DBG) log(getName() + "\n"); + sendMessage(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0)); + } + public boolean processMessage(Message msg) { + switch (msg.what) { + case EVENT_RSSI_CHANGE: + mCurrentSignalLevel = calculateSignalLevel(msg.arg1); + if (mCurrentSignalLevel <= RSSI_LEVEL_CUTOFF) { + sendPoorLinkDetected(); + } else if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) { + //stay here; + } else { + //We dont need frequent RSSI monitoring any more + transitionTo(mOnlineWatchState); + } break; - case CMD_ARP_CHECK: - if (msg.arg1 == mArpToken) { - if (doArpTest(SINGLE_ARP_CHECK) != true) { - if (DBG) log("single ARP fail, full ARP check"); - //do a full test - if (doArpTest(FULL_ARP_CHECK) != true) { - if (DBG) log("notify full ARP fail, level: " + mCurrentSignalLevel); - mWsmChannel.sendMessage(POOR_LINK_DETECTED); - } - } + case CMD_RSSI_FETCH: + if (msg.arg1 == mRssiFetchToken) { + mWsmChannel.sendMessage(RSSI_FETCH); + sendMessageDelayed(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0), + mRssiFetchIntervalMs); + } + break; + case RSSI_FETCH_SUCCEEDED: + int rssi = msg.arg1; + if (DBG) log("RSSI_FETCH_SUCCEEDED: " + rssi); + if (msg.arg1 < RSSI_MONITOR_THRESHOLD) { + mRssiMonitorCount++; + } else { + mRssiMonitorCount = 0; + } - if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) { - if (DBG) log("Continue ARP check, rssi level: " + mCurrentSignalLevel); - sendMessageDelayed(obtainMessage(CMD_ARP_CHECK, ++mArpToken, 0), - mArpCheckIntervalMs); - } + if (mRssiMonitorCount > RSSI_MONITOR_COUNT) { + sendPoorLinkDetected(); + ++mRssiFetchToken; } break; + case RSSI_FETCH_FAILED: + //can happen if we are waiting to get a disconnect notification + if (DBG) log("RSSI_FETCH_FAILED"); + break; default: return NOT_HANDLED; } return HANDLED; } - } + } /* Child state of ConnectedState indicating that we are online * and there is nothing to do */ class OnlineState extends State { + @Override + public void enter() { + if (DBG) log(getName() + "\n"); + } } private boolean shouldCheckWalledGarden() { @@ -794,6 +882,20 @@ public class WifiWatchdogStateMachine extends StateMachine { return success; } + private int calculateSignalLevel(int rssi) { + int signalLevel = WifiManager.calculateSignalLevel(rssi, + WifiManager.RSSI_LEVELS); + if (DBG) log("RSSI current: " + mCurrentSignalLevel + "new: " + rssi + ", " + signalLevel); + return signalLevel; + } + + private void sendPoorLinkDetected() { + if (DBG) log("send POOR_LINK_DETECTED " + mWifiInfo); + mWsmChannel.sendMessage(POOR_LINK_DETECTED); + mLastAvoidedBssid = mWifiInfo.getBSSID(); + mLastBssidAvoidedTime = android.os.SystemClock.elapsedRealtime(); + } + /** * Convenience function for retrieving a single secure settings value * as a string with a default value. @@ -844,11 +946,11 @@ public class WifiWatchdogStateMachine extends StateMachine { return Settings.Secure.putInt(cr, name, value ? 1 : 0); } - private void log(String s) { + private static void log(String s) { Log.d(TAG, s); } - private void loge(String s) { + private static void loge(String s) { Log.e(TAG, s); } } |