Loading core/java/android/provider/Settings.java +8 −0 Original line number Diff line number Diff line Loading @@ -3128,6 +3128,14 @@ public final class Settings { public static final String WIFI_WATCHDOG_ARP_CHECK_INTERVAL_MS = "wifi_watchdog_arp_interval_ms"; /** * ms delay interval between rssi polling when the signal is known to be weak * @hide */ public static final String WIFI_WATCHDOG_RSSI_FETCH_INTERVAL_MS = "wifi_watchdog_rssi_fetch_interval_ms"; /** * ms delay before rechecking a connect SSID for walled garden with a http download. * @hide Loading wifi/java/android/net/wifi/WifiStateMachine.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading wifi/java/android/net/wifi/WifiWatchdogStateMachine.java +141 −39 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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()) { Loading @@ -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); Loading Loading @@ -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 + "]"); Loading @@ -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() { Loading @@ -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); Loading Loading @@ -435,6 +470,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) { Loading @@ -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: Loading @@ -463,6 +505,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) { Loading Loading @@ -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( Loading Loading @@ -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 { Loading @@ -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 { Loading @@ -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: Loading Loading @@ -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 } } Loading @@ -692,32 +741,67 @@ 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; 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); default: return NOT_HANDLED; } return HANDLED; } } if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) { if (DBG) log("Continue ARP check, rssi level: " + mCurrentSignalLevel); sendMessageDelayed(obtainMessage(CMD_ARP_CHECK, ++mArpToken, 0), mArpCheckIntervalMs); 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_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 (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; } Loading @@ -729,6 +813,10 @@ public class WifiWatchdogStateMachine extends StateMachine { * and there is nothing to do */ class OnlineState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); } } private boolean shouldCheckWalledGarden() { Loading Loading @@ -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. Loading Loading @@ -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); } } Loading
core/java/android/provider/Settings.java +8 −0 Original line number Diff line number Diff line Loading @@ -3128,6 +3128,14 @@ public final class Settings { public static final String WIFI_WATCHDOG_ARP_CHECK_INTERVAL_MS = "wifi_watchdog_arp_interval_ms"; /** * ms delay interval between rssi polling when the signal is known to be weak * @hide */ public static final String WIFI_WATCHDOG_RSSI_FETCH_INTERVAL_MS = "wifi_watchdog_rssi_fetch_interval_ms"; /** * ms delay before rechecking a connect SSID for walled garden with a http download. * @hide Loading
wifi/java/android/net/wifi/WifiStateMachine.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading
wifi/java/android/net/wifi/WifiWatchdogStateMachine.java +141 −39 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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()) { Loading @@ -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); Loading Loading @@ -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 + "]"); Loading @@ -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() { Loading @@ -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); Loading Loading @@ -435,6 +470,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) { Loading @@ -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: Loading @@ -463,6 +505,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) { Loading Loading @@ -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( Loading Loading @@ -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 { Loading @@ -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 { Loading @@ -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: Loading Loading @@ -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 } } Loading @@ -692,32 +741,67 @@ 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; 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); default: return NOT_HANDLED; } return HANDLED; } } if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) { if (DBG) log("Continue ARP check, rssi level: " + mCurrentSignalLevel); sendMessageDelayed(obtainMessage(CMD_ARP_CHECK, ++mArpToken, 0), mArpCheckIntervalMs); 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_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 (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; } Loading @@ -729,6 +813,10 @@ public class WifiWatchdogStateMachine extends StateMachine { * and there is nothing to do */ class OnlineState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); } } private boolean shouldCheckWalledGarden() { Loading Loading @@ -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. Loading Loading @@ -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); } }