diff options
author | Isaac Levy <ilevy@google.com> | 2011-07-06 13:54:48 -0700 |
---|---|---|
committer | Isaac Levy <ilevy@google.com> | 2011-07-06 13:54:48 -0700 |
commit | a7bc1135c270fd4a84ab7ad45b7194e9b580300e (patch) | |
tree | ccde642a2b28cb3fc18469a1cdd0b9187e87c2fd /wifi/java | |
parent | e58e9b8c8297dc9ae407c132d0f0983e63be46f0 (diff) | |
download | frameworks_base-a7bc1135c270fd4a84ab7ad45b7194e9b580300e.zip frameworks_base-a7bc1135c270fd4a84ab7ad45b7194e9b580300e.tar.gz frameworks_base-a7bc1135c270fd4a84ab7ad45b7194e9b580300e.tar.bz2 |
Moved WifiWatchdogService and DnsPinger
- Moved WWS and DnsPinger in prep for StateMachine rewrite
intent.
Change-Id: I912ca80d31ee2ded99eb345a2e5a55d01bd9910c
Diffstat (limited to 'wifi/java')
-rw-r--r-- | wifi/java/android/net/wifi/WifiWatchdogService.java | 765 |
1 files changed, 765 insertions, 0 deletions
diff --git a/wifi/java/android/net/wifi/WifiWatchdogService.java b/wifi/java/android/net/wifi/WifiWatchdogService.java new file mode 100644 index 0000000..bce4b3a --- /dev/null +++ b/wifi/java/android/net/wifi/WifiWatchdogService.java @@ -0,0 +1,765 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.database.ContentObserver; +import android.net.ConnectivityManager; +import android.net.DnsPinger; +import android.net.NetworkInfo; +import android.net.Uri; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.SystemClock; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Slog; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashSet; +import java.util.List; +import java.util.Scanner; + +/** + * {@link WifiWatchdogService} monitors the initial connection to a Wi-Fi + * network with multiple access points. After the framework successfully + * connects to an access point, the watchdog verifies connectivity by 'pinging' + * the configured DNS server using {@link DnsPinger}. + * <p> + * On DNS check failure, the BSSID is blacklisted if it is reasonably likely + * that another AP might have internet access; otherwise the SSID is disabled. + * <p> + * On DNS success, the WatchdogService initiates a walled garden check via an + * http get. A browser windows is activated if a walled garden is detected. + * + * @hide + */ +public class WifiWatchdogService { + + private static final String WWS_TAG = "WifiWatchdogService"; + + private static final boolean VDBG = true; + private static final boolean DBG = true; + + // Used for verbose logging + private String mDNSCheckLogStr; + + private Context mContext; + private ContentResolver mContentResolver; + private WifiManager mWifiManager; + + private WifiWatchdogHandler mHandler; + + private DnsPinger mDnsPinger; + + private IntentFilter mIntentFilter; + private BroadcastReceiver mBroadcastReceiver; + private boolean mBroadcastsEnabled; + + private static final int WIFI_SIGNAL_LEVELS = 4; + + /** + * Low signal is defined as less than or equal to cut off + */ + private static final int LOW_SIGNAL_CUTOFF = 0; + + private static final long MIN_LOW_SIGNAL_CHECK_INTERVAL = 2 * 60 * 1000; + private static final long MIN_SINGLE_DNS_CHECK_INTERVAL = 10 * 60 * 1000; + private static final long MIN_WALLED_GARDEN_INTERVAL = 15 * 60 * 1000; + + private static final int MAX_CHECKS_PER_SSID = 9; + private static final int NUM_DNS_PINGS = 7; + private static double MIN_RESPONSE_RATE = 0.50; + + // TODO : Adjust multiple DNS downward to 250 on repeated failure + // private static final int MULTI_DNS_PING_TIMEOUT_MS = 250; + + private static final int DNS_PING_TIMEOUT_MS = 800; + private static final long DNS_PING_INTERVAL = 250; + + private static final long BLACKLIST_FOLLOWUP_INTERVAL = 15 * 1000; + + private Status mStatus = new Status(); + + private static class Status { + String bssid = ""; + String ssid = ""; + + HashSet<String> allBssids = new HashSet<String>(); + int numFullDNSchecks = 0; + + long lastSingleCheckTime = -24 * 60 * 60 * 1000; + long lastWalledGardenCheckTime = -24 * 60 * 60 * 1000; + + WatchdogState state = WatchdogState.INACTIVE; + + // Info for dns check + int dnsCheckTries = 0; + int dnsCheckSuccesses = 0; + + public int signal = -200; + + } + + private enum WatchdogState { + /** + * Full DNS check in progress + */ + DNS_FULL_CHECK, + + /** + * Walled Garden detected, will pop up browser next round. + */ + WALLED_GARDEN_DETECTED, + + /** + * DNS failed, will blacklist/disable AP next round + */ + DNS_CHECK_FAILURE, + + /** + * Online or displaying walled garden auth page + */ + CHECKS_COMPLETE, + + /** + * Watchdog idle, network has been blacklisted or received disconnect + * msg + */ + INACTIVE, + + BLACKLISTED_AP + } + + public WifiWatchdogService(Context context) { + mContext = context; + mContentResolver = context.getContentResolver(); + mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context, + ConnectivityManager.TYPE_WIFI); + + HandlerThread handlerThread = new HandlerThread("WifiWatchdogServiceThread"); + handlerThread.start(); + mHandler = new WifiWatchdogHandler(handlerThread.getLooper()); + + setupNetworkReceiver(); + + // The content observer to listen needs a handler, which createThread + // creates + registerForSettingsChanges(); + + // Start things off + if (isWatchdogEnabled()) { + mHandler.sendEmptyMessage(WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT); + } + } + + /** + * + */ + private void setupNetworkReceiver() { + mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + mHandler.sendMessage(mHandler.obtainMessage( + WifiWatchdogHandler.MESSAGE_NETWORK_EVENT, + intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO) + )); + } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { + mHandler.sendEmptyMessage(WifiWatchdogHandler.RSSI_CHANGE_EVENT); + } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { + mHandler.sendEmptyMessage(WifiWatchdogHandler.SCAN_RESULTS_AVAILABLE); + } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { + mHandler.sendMessage(mHandler.obtainMessage( + WifiWatchdogHandler.WIFI_STATE_CHANGE, + intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 4))); + } + } + }; + + mIntentFilter = new IntentFilter(); + mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); + mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + } + + /** + * Observes the watchdog on/off setting, and takes action when changed. + */ + private void registerForSettingsChanges() { + ContentObserver contentObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + mHandler.sendEmptyMessage((WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT)); + } + }; + + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), + false, contentObserver); + } + + private void handleNewConnection() { + WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); + String newSsid = wifiInfo.getSSID(); + String newBssid = wifiInfo.getBSSID(); + + if (VDBG) { + Slog.v(WWS_TAG, String.format("handleConnected:: old (%s, %s) ==> new (%s, %s)", + mStatus.ssid, mStatus.bssid, newSsid, newBssid)); + } + + if (TextUtils.isEmpty(newSsid) || TextUtils.isEmpty(newBssid)) { + return; + } + + if (!TextUtils.equals(mStatus.ssid, newSsid)) { + mStatus = new Status(); + mStatus.ssid = newSsid; + } + + mStatus.bssid = newBssid; + mStatus.allBssids.add(newBssid); + mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS); + + initDnsFullCheck(); + } + + public void updateRssi() { + WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); + if (!TextUtils.equals(mStatus.ssid, wifiInfo.getSSID()) || + !TextUtils.equals(mStatus.bssid, wifiInfo.getBSSID())) { + return; + } + + mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS); + } + + /** + * Single step in state machine + */ + private void handleStateStep() { + // Slog.v(WWS_TAG, "handleStateStep:: " + mStatus.state); + + switch (mStatus.state) { + case DNS_FULL_CHECK: + if (VDBG) { + Slog.v(WWS_TAG, "DNS_FULL_CHECK: " + mDNSCheckLogStr); + } + + long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), + DNS_PING_TIMEOUT_MS); + + mStatus.dnsCheckTries++; + if (pingResponseTime >= 0) + mStatus.dnsCheckSuccesses++; + + if (DBG) { + if (pingResponseTime >= 0) { + mDNSCheckLogStr += " | " + pingResponseTime; + } else { + mDNSCheckLogStr += " | " + "x"; + } + } + + switch (currentDnsCheckStatus()) { + case SUCCESS: + if (DBG) { + Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Success"); + } + doWalledGardenCheck(); + break; + case FAILURE: + if (DBG) { + Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Failure"); + } + mStatus.state = WatchdogState.DNS_CHECK_FAILURE; + break; + case INCOMPLETE: + // Taking no action + break; + } + break; + case DNS_CHECK_FAILURE: + WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); + if (!mStatus.ssid.equals(wifiInfo.getSSID()) || + !mStatus.bssid.equals(wifiInfo.getBSSID())) { + Slog.i(WWS_TAG, "handleState DNS_CHECK_FAILURE:: network has changed!"); + mStatus.state = WatchdogState.INACTIVE; + break; + } + + if (mStatus.numFullDNSchecks >= mStatus.allBssids.size() || + mStatus.numFullDNSchecks >= MAX_CHECKS_PER_SSID) { + disableAP(wifiInfo); + } else { + blacklistAP(); + } + break; + case WALLED_GARDEN_DETECTED: + popUpBrowser(); + mStatus.state = WatchdogState.CHECKS_COMPLETE; + break; + case BLACKLISTED_AP: + WifiInfo wifiInfo2 = mWifiManager.getConnectionInfo(); + if (wifiInfo2.getSupplicantState() != SupplicantState.COMPLETED) { + Slog.d(WWS_TAG, + "handleState::BlacklistedAP - offline, but didn't get disconnect!"); + mStatus.state = WatchdogState.INACTIVE; + break; + } + if (mStatus.bssid.equals(wifiInfo2.getBSSID())) { + Slog.d(WWS_TAG, "handleState::BlacklistedAP - connected to same bssid"); + if (!handleSingleDnsCheck()) { + disableAP(wifiInfo2); + break; + } + } + + Slog.d(WWS_TAG, "handleState::BlacklistedAP - Simiulating a new connection"); + handleNewConnection(); + break; + } + } + + private void doWalledGardenCheck() { + if (!isWalledGardenTestEnabled()) { + if (VDBG) + Slog.v(WWS_TAG, "Skipping walled garden check - disabled"); + mStatus.state = WatchdogState.CHECKS_COMPLETE; + return; + } + long waitTime = waitTime(MIN_WALLED_GARDEN_INTERVAL, + mStatus.lastWalledGardenCheckTime); + if (waitTime > 0) { + if (VDBG) { + Slog.v(WWS_TAG, "Skipping walled garden check - wait " + + waitTime + " ms."); + } + mStatus.state = WatchdogState.CHECKS_COMPLETE; + return; + } + + mStatus.lastWalledGardenCheckTime = SystemClock.elapsedRealtime(); + if (isWalledGardenConnection()) { + if (DBG) + Slog.d(WWS_TAG, + "Walled garden test complete - walled garden detected"); + mStatus.state = WatchdogState.WALLED_GARDEN_DETECTED; + } else { + if (DBG) + Slog.d(WWS_TAG, "Walled garden test complete - online"); + mStatus.state = WatchdogState.CHECKS_COMPLETE; + } + } + + private boolean handleSingleDnsCheck() { + mStatus.lastSingleCheckTime = SystemClock.elapsedRealtime(); + long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), + DNS_PING_TIMEOUT_MS); + if (DBG) { + Slog.d(WWS_TAG, "Ran a single DNS ping. Response time: " + responseTime); + } + if (responseTime < 0) { + return false; + } + return true; + + } + + /** + * @return Delay in MS before next single DNS check can proceed. + */ + private long timeToNextScheduledDNSCheck() { + if (mStatus.signal > LOW_SIGNAL_CUTOFF) { + return waitTime(MIN_SINGLE_DNS_CHECK_INTERVAL, mStatus.lastSingleCheckTime); + } else { + return waitTime(MIN_LOW_SIGNAL_CHECK_INTERVAL, mStatus.lastSingleCheckTime); + } + } + + /** + * Helper to return wait time left given a min interval and last run + * + * @param interval minimum wait interval + * @param lastTime last time action was performed in + * SystemClock.elapsedRealtime() + * @return non negative time to wait + */ + private static long waitTime(long interval, long lastTime) { + long wait = interval + lastTime - SystemClock.elapsedRealtime(); + return wait > 0 ? wait : 0; + } + + private void popUpBrowser() { + Uri uri = Uri.parse("http://www.google.com"); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | + Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } + + private void disableAP(WifiInfo info) { + // TODO : Unban networks if they had low signal ? + Slog.i(WWS_TAG, String.format("Disabling current SSID, %s [bssid %s]. " + + "numChecks %d, numAPs %d", mStatus.ssid, mStatus.bssid, + mStatus.numFullDNSchecks, mStatus.allBssids.size())); + mWifiManager.disableNetwork(info.getNetworkId()); + mStatus.state = WatchdogState.INACTIVE; + } + + private void blacklistAP() { + Slog.i(WWS_TAG, String.format("Blacklisting current BSSID %s [ssid %s]. " + + "numChecks %d, numAPs %d", mStatus.bssid, mStatus.ssid, + mStatus.numFullDNSchecks, mStatus.allBssids.size())); + + mWifiManager.addToBlacklist(mStatus.bssid); + mWifiManager.reassociate(); + mStatus.state = WatchdogState.BLACKLISTED_AP; + } + + /** + * Checks the scan for new BBIDs using current mSsid + */ + private void updateBssids() { + String curSsid = mStatus.ssid; + HashSet<String> bssids = mStatus.allBssids; + List<ScanResult> results = mWifiManager.getScanResults(); + int oldNumBssids = bssids.size(); + + if (results == null) { + if (VDBG) { + Slog.v(WWS_TAG, "updateBssids: Got null scan results!"); + } + return; + } + + for (ScanResult result : results) { + if (result != null && curSsid.equals(result.SSID)) + bssids.add(result.BSSID); + } + + // if (VDBG && bssids.size() - oldNumBssids > 0) { + // Slog.v(WWS_TAG, + // String.format("updateBssids:: Found %d new APs (total %d) on SSID %s", + // bssids.size() - oldNumBssids, bssids.size(), curSsid)); + // } + } + + enum DnsCheckStatus { + SUCCESS, + FAILURE, + INCOMPLETE + } + + /** + * Computes the current results of the dns check, ends early if outcome is + * assured. + */ + private DnsCheckStatus currentDnsCheckStatus() { + /** + * After a full ping count, if we have more responses than this cutoff, + * the outcome is success; else it is 'failure'. + */ + double pingResponseCutoff = MIN_RESPONSE_RATE * NUM_DNS_PINGS; + int remainingChecks = NUM_DNS_PINGS - mStatus.dnsCheckTries; + + /** + * Our final success count will be at least this big, so we're + * guaranteed to succeed. + */ + if (mStatus.dnsCheckSuccesses >= pingResponseCutoff) { + return DnsCheckStatus.SUCCESS; + } + + /** + * Our final count will be at most the current count plus the remaining + * pings - we're guaranteed to fail. + */ + if (remainingChecks + mStatus.dnsCheckSuccesses < pingResponseCutoff) { + return DnsCheckStatus.FAILURE; + } + + return DnsCheckStatus.INCOMPLETE; + } + + private void initDnsFullCheck() { + if (DBG) { + Slog.d(WWS_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime()); + } + mStatus.numFullDNSchecks++; + mStatus.dnsCheckSuccesses = 0; + mStatus.dnsCheckTries = 0; + mStatus.state = WatchdogState.DNS_FULL_CHECK; + + if (DBG) { + mDNSCheckLogStr = String.format("Dns Check %d. Pinging %s on ssid [%s]: ", + mStatus.numFullDNSchecks, mDnsPinger.getDns(), + mStatus.ssid); + } + } + + /** + * DNS based detection techniques do not work at all hotspots. The one sure + * way to check a walled garden is to see if a URL fetch on a known address + * fetches the data we expect + */ + private boolean isWalledGardenConnection() { + InputStream in = null; + HttpURLConnection urlConnection = null; + try { + URL url = new URL(getWalledGardenUrl()); + urlConnection = (HttpURLConnection) url.openConnection(); + in = new BufferedInputStream(urlConnection.getInputStream()); + Scanner scanner = new Scanner(in); + if (scanner.findInLine(getWalledGardenPattern()) != null) { + return false; + } else { + return true; + } + } catch (IOException e) { + return false; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + } + } + if (urlConnection != null) + urlConnection.disconnect(); + } + } + + /** + * There is little logic inside this class, instead methods of the form + * "handle___" are called in the main {@link WifiWatchdogService}. + */ + private class WifiWatchdogHandler extends Handler { + /** + * Major network event, object is NetworkInfo + */ + static final int MESSAGE_NETWORK_EVENT = 1; + /** + * Change in settings, no object + */ + static final int MESSAGE_CONTEXT_EVENT = 2; + + /** + * Change in signal strength + */ + static final int RSSI_CHANGE_EVENT = 3; + static final int SCAN_RESULTS_AVAILABLE = 4; + + static final int WIFI_STATE_CHANGE = 5; + + /** + * Single step of state machine. One DNS check, or one WalledGarden + * check, or one external action. We separate out external actions to + * increase chance of detecting that a check failure is caused by change + * in network status. Messages should have an arg1 which to sync status + * messages. + */ + static final int CHECK_SEQUENCE_STEP = 10; + static final int SINGLE_DNS_CHECK = 11; + + /** + * @param looper + */ + public WifiWatchdogHandler(Looper looper) { + super(looper); + } + + boolean singleCheckQueued = false; + long queuedSingleDnsCheckArrival; + + /** + * Sends a singleDnsCheck message with shortest time - guards against + * multiple. + */ + private boolean queueSingleDnsCheck() { + long delay = timeToNextScheduledDNSCheck(); + long newArrival = delay + SystemClock.elapsedRealtime(); + if (singleCheckQueued && queuedSingleDnsCheckArrival <= newArrival) + return true; + queuedSingleDnsCheckArrival = newArrival; + singleCheckQueued = true; + removeMessages(SINGLE_DNS_CHECK); + return sendMessageDelayed(obtainMessage(SINGLE_DNS_CHECK), delay); + } + + boolean checkSequenceQueued = false; + long queuedCheckSequenceArrival; + + /** + * Sends a state_machine_step message if the delay requested is lower + * than the current delay. + */ + private boolean sendCheckSequenceStep(long delay) { + long newArrival = delay + SystemClock.elapsedRealtime(); + if (checkSequenceQueued && queuedCheckSequenceArrival <= newArrival) + return true; + queuedCheckSequenceArrival = newArrival; + checkSequenceQueued = true; + removeMessages(CHECK_SEQUENCE_STEP); + return sendMessageDelayed(obtainMessage(CHECK_SEQUENCE_STEP), delay); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case CHECK_SEQUENCE_STEP: + checkSequenceQueued = false; + handleStateStep(); + if (mStatus.state == WatchdogState.CHECKS_COMPLETE) { + queueSingleDnsCheck(); + } else if (mStatus.state == WatchdogState.DNS_FULL_CHECK) { + sendCheckSequenceStep(DNS_PING_INTERVAL); + } else if (mStatus.state == WatchdogState.BLACKLISTED_AP) { + sendCheckSequenceStep(BLACKLIST_FOLLOWUP_INTERVAL); + } else if (mStatus.state != WatchdogState.INACTIVE) { + sendCheckSequenceStep(0); + } + return; + case MESSAGE_NETWORK_EVENT: + if (!mBroadcastsEnabled) { + Slog.e(WWS_TAG, + "MessageNetworkEvent - WatchdogService not enabled... returning"); + return; + } + NetworkInfo info = (NetworkInfo) msg.obj; + switch (info.getState()) { + case DISCONNECTED: + mStatus.state = WatchdogState.INACTIVE; + return; + case CONNECTED: + handleNewConnection(); + sendCheckSequenceStep(0); + } + return; + case SINGLE_DNS_CHECK: + singleCheckQueued = false; + if (mStatus.state != WatchdogState.CHECKS_COMPLETE) { + Slog.d(WWS_TAG, "Single check returning, curState: " + mStatus.state); + break; + } + + if (!handleSingleDnsCheck()) { + initDnsFullCheck(); + sendCheckSequenceStep(0); + } else { + queueSingleDnsCheck(); + } + + break; + case RSSI_CHANGE_EVENT: + updateRssi(); + if (mStatus.state == WatchdogState.CHECKS_COMPLETE) + queueSingleDnsCheck(); + break; + case SCAN_RESULTS_AVAILABLE: + updateBssids(); + break; + case WIFI_STATE_CHANGE: + if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) { + Slog.i(WWS_TAG, "WifiStateDisabling -- Resetting WatchdogState"); + mStatus = new Status(); + } + break; + case MESSAGE_CONTEXT_EVENT: + if (isWatchdogEnabled() && !mBroadcastsEnabled) { + mContext.registerReceiver(mBroadcastReceiver, mIntentFilter); + mBroadcastsEnabled = true; + Slog.i(WWS_TAG, "WifiWatchdogService enabled"); + } else if (!isWatchdogEnabled() && mBroadcastsEnabled) { + mContext.unregisterReceiver(mBroadcastReceiver); + removeMessages(SINGLE_DNS_CHECK); + removeMessages(CHECK_SEQUENCE_STEP); + mBroadcastsEnabled = false; + Slog.i(WWS_TAG, "WifiWatchdogService disabled"); + } + break; + } + } + } + + public void dump(PrintWriter pw) { + pw.print("WatchdogStatus: "); + pw.print("State " + mStatus.state); + pw.println(", network [" + mStatus.ssid + ", " + mStatus.bssid + "]"); + pw.print("checkCount " + mStatus.numFullDNSchecks); + pw.println(", bssids: " + mStatus.allBssids); + pw.print(", hasCheckMessages? " + + mHandler.hasMessages(WifiWatchdogHandler.CHECK_SEQUENCE_STEP)); + pw.println(" hasSingleCheckMessages? " + + mHandler.hasMessages(WifiWatchdogHandler.SINGLE_DNS_CHECK)); + pw.println("DNS check log str: " + mDNSCheckLogStr); + pw.println("lastSingleCheck: " + mStatus.lastSingleCheckTime); + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED + */ + private Boolean isWalledGardenTestEnabled() { + return Settings.Secure.getInt(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1; + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL + */ + private String getWalledGardenUrl() { + String url = Settings.Secure.getString(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL); + if (TextUtils.isEmpty(url)) + return "http://www.google.com/"; + return url; + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN + */ + private String getWalledGardenPattern() { + String pattern = Settings.Secure.getString(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN); + if (TextUtils.isEmpty(pattern)) + return "<title>.*Google.*</title>"; + return pattern; + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON + */ + private boolean isWatchdogEnabled() { + return Settings.Secure.getInt(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1; + } +} |