/*
 * 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 com.android.server;

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.LinkProperties;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.Random;
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 whether the DNS server is
 * reachable. If not, the watchdog blacklists the current access point, leading
 * to a connection on another access point within the same network.
 * <p>
 * The watchdog has a few safeguards:
 * <ul>
 * <li>Only monitor networks with multiple access points
 * <li>Only check at most {@link #getMaxApChecks()} different access points
 * within the network before giving up
 * <p>
 * The watchdog checks for connectivity on an access point by ICMP pinging the
 * DNS. There are settings that allow disabling the watchdog, or tweaking the
 * acceptable packet loss (and other various parameters).
 * <p>
 * The core logic of the watchdog is done on the main watchdog thread. Wi-Fi
 * callbacks can come in on other threads, so we must queue messages to the main
 * watchdog thread's handler. Most (if not all) state is only written to from
 * the main thread.
 * 
 * {@hide}
 */
public class WifiWatchdogService {
    private static final String TAG = "WifiWatchdogService";
    private static final boolean V = false;
    private static final boolean D = true;

    private Context mContext;
    private ContentResolver mContentResolver;
    private WifiManager mWifiManager;
    private ConnectivityManager mConnectivityManager;

    /**
     * The main watchdog thread.
     */
    private WifiWatchdogThread mThread;
    /**
     * The handler for the main watchdog thread.
     */
    private WifiWatchdogHandler mHandler;

    private ContentObserver mContentObserver;

    /**
     * The current watchdog state. Only written from the main thread!
     */
    private WatchdogState mState = WatchdogState.IDLE;
    /**
     * The SSID of the network that the watchdog is currently monitoring. Only
     * touched in the main thread!
     */
    private String mSsid;
    /**
     * The number of access points in the current network ({@link #mSsid}) that
     * have been checked. Only touched in the main thread, using getter/setter methods.
     */
    private int mBssidCheckCount;
    /** Whether the current AP check should be canceled. */
    private boolean mShouldCancel;

    WifiWatchdogService(Context context) {
        mContext = context;
        mContentResolver = context.getContentResolver();
        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        createThread();
        
        // The content observer to listen needs a handler, which createThread creates
        registerForSettingsChanges();
        if (isWatchdogEnabled()) {
            registerForWifiBroadcasts();
        }
        
        if (V) {
            myLogV("WifiWatchdogService: Created");
        }
    }

    /**
     * Observes the watchdog on/off setting, and takes action when changed.
     */
    private void registerForSettingsChanges() {
        ContentResolver contentResolver = mContext.getContentResolver();
        contentResolver.registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), false,
                mContentObserver = new ContentObserver(mHandler) {
            @Override
            public void onChange(boolean selfChange) {
                if (isWatchdogEnabled()) {
                    registerForWifiBroadcasts();
                } else {
                    unregisterForWifiBroadcasts();
                    if (mHandler != null) {
                        mHandler.disableWatchdog();
                    }
                }
            }
        });
    }

    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON
     */
    private boolean isWatchdogEnabled() {
        return Settings.Secure.getInt(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1;
    }
    
    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_AP_COUNT
     */
    private int getApCount() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_AP_COUNT, 2);
    }
    
    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT
     */
    private int getInitialIgnoredPingCount() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT , 2);
    }

    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_COUNT
     */
    private int getPingCount() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_PING_COUNT, 4);
    }
    
    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_TIMEOUT_MS
     */
    private int getPingTimeoutMs() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS, 500);
    }
    
    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_DELAY_MS
     */
    private int getPingDelayMs() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS, 250);
    }

    /**
     * @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_ACCEPTABLE_PACKET_LOSS_PERCENTAGE
     */
    private int getAcceptablePacketLossPercentage() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, 25);
    }
    
    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_MAX_AP_CHECKS
     */
    private int getMaxApChecks() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_MAX_AP_CHECKS, 7);
    }
    
    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED
     */
    private boolean isBackgroundCheckEnabled() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, 1) == 1;
    }
    
    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS
     */
    private int getBackgroundCheckDelayMs() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, 60000);
    }
    
    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS
     */
    private int getBackgroundCheckTimeoutMs() {
        return Settings.Secure.getInt(mContentResolver,
            Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, 1000);
    }

    /**
     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WATCH_LIST
     * @return the comma-separated list of SSIDs
     */
    private String getWatchList() {
        return Settings.Secure.getString(mContentResolver,
                Settings.Secure.WIFI_WATCHDOG_WATCH_LIST);
    }
    
    /**
     * Registers to receive the necessary Wi-Fi broadcasts.
     */
    private void registerForWifiBroadcasts() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        mContext.registerReceiver(mReceiver, intentFilter);
    }

    /**
     * Unregisters from receiving the Wi-Fi broadcasts.
     */
    private void unregisterForWifiBroadcasts() {
        mContext.unregisterReceiver(mReceiver);
    }

    /**
     * Creates the main watchdog thread, including waiting for the handler to be
     * created.
     */
    private void createThread() {
        mThread = new WifiWatchdogThread();
        mThread.start();
        waitForHandlerCreation();
    }

    /**
     * Unregister broadcasts and quit the watchdog thread
     */
    //TODO: Change back to running WWS when needed
//    private void quit() {
//        unregisterForWifiBroadcasts();
//        mContext.getContentResolver().unregisterContentObserver(mContentObserver);
//        mHandler.removeAllActions();
//        mHandler.getLooper().quit();
//    }

    /**
     * Waits for the main watchdog thread to create the handler.
     */
    private void waitForHandlerCreation() {
        synchronized(this) {
            while (mHandler == null) {
                try {
                    // Wait for the handler to be set by the other thread
                    wait();
                } catch (InterruptedException e) {
                    Slog.e(TAG, "Interrupted while waiting on handler.");
                }
            }
        }
    }

    // Utility methods
    
    /**
     * Logs with the current thread.
     */
    private static void myLogV(String message) {
        Slog.v(TAG, "(" + Thread.currentThread().getName() + ") " + message);
    }
    
    private static void myLogD(String message) {
        Slog.d(TAG, "(" + Thread.currentThread().getName() + ") " + message);
    }
    
    /**
     * Gets the first DNS of the current AP.
     * 
     * @return The first DNS of the current AP.
     */
    private InetAddress getDns() {
        if (mConnectivityManager == null) {
            mConnectivityManager = (ConnectivityManager)mContext.getSystemService(
                    Context.CONNECTIVITY_SERVICE);
        }

        LinkProperties linkProperties = mConnectivityManager.getLinkProperties(
                ConnectivityManager.TYPE_WIFI);
        if (linkProperties == null) return null;

        Collection<InetAddress> dnses = linkProperties.getDnses();
        if (dnses == null || dnses.size() == 0) return null;

        return dnses.iterator().next();
    }

    /**
     * Checks whether the DNS can be reached using multiple attempts according
     * to the current setting values.
     * 
     * @return Whether the DNS is reachable
     */
    private boolean checkDnsConnectivity() {
        InetAddress dns = getDns();
        if (dns == null) {
            if (V) {
                myLogV("checkDnsConnectivity: Invalid DNS, returning false");
            }
            return false;
        }

        if (V) {
            myLogV("checkDnsConnectivity: Checking " + dns.getHostAddress() + " for connectivity");
        }

        int numInitialIgnoredPings = getInitialIgnoredPingCount();
        int numPings = getPingCount();
        int pingDelay = getPingDelayMs();
        int acceptableLoss = getAcceptablePacketLossPercentage();

        /** See {@link Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT} */
        int ignoredPingCounter = 0;
        int pingCounter = 0;
        int successCounter = 0;

        // No connectivity check needed
        if (numPings == 0) {
            return true;
        }

        // Do the initial pings that we ignore
        for (; ignoredPingCounter < numInitialIgnoredPings; ignoredPingCounter++) {
            if (shouldCancel()) return false;

            boolean dnsAlive = DnsPinger.isDnsReachable(dns, getPingTimeoutMs());
            if (dnsAlive) {
                /*
                 * Successful "ignored" pings are *not* ignored (they count in the total number
                 * of pings), but failures are really ignored.
                 */

                // TODO: This is confusing logic and should be rewitten
                // Here, successful 'ignored' pings are interpreted as a success in the below loop
                pingCounter++;
                successCounter++;
            }

            if (V) {
                Slog.v(TAG, (dnsAlive ? "  +" : "  Ignored: -"));
            }

            if (shouldCancel()) return false;

            try {
                Thread.sleep(pingDelay);
            } catch (InterruptedException e) {
                Slog.w(TAG, "Interrupted while pausing between pings", e);
            }
        }

        // Do the pings that we use to measure packet loss
        for (; pingCounter < numPings; pingCounter++) {
            if (shouldCancel()) return false;

            if (DnsPinger.isDnsReachable(dns, getPingTimeoutMs())) {
                successCounter++;
                if (V) {
                    Slog.v(TAG, "  +");
                }
            } else {
                if (V) {
                    Slog.v(TAG, "  -");
                }
            }

            if (shouldCancel()) return false;

            try {
                Thread.sleep(pingDelay);
            } catch (InterruptedException e) {
                Slog.w(TAG, "Interrupted while pausing between pings", e);
            }
        }

        //TODO: Integer division might cause problems down the road...
        int packetLossPercentage = 100 * (numPings - successCounter) / numPings;
        if (D) {
            Slog.d(TAG, packetLossPercentage
                    + "% packet loss (acceptable is " + acceptableLoss + "%)");
        }

        return !shouldCancel() && (packetLossPercentage <= acceptableLoss);
    }

    private boolean backgroundCheckDnsConnectivity() {
        InetAddress dns = getDns();

        if (dns == null) {
            if (V) {
                myLogV("backgroundCheckDnsConnectivity: DNS is empty, returning false");
            }
            return false;
        }

        if (V) {
            myLogV("backgroundCheckDnsConnectivity: Background checking " +
                    dns.getHostAddress() + " for connectivity");
        }

        return DnsPinger.isDnsReachable(dns, getBackgroundCheckTimeoutMs());
    }

    /**
     * Signals the current action to cancel.
     */
    private void cancelCurrentAction() {
        mShouldCancel = true;
    }
    
    /**
     * Helper to check whether to cancel. 
     * 
     * @return Whether to cancel processing the action.
     */
    private boolean shouldCancel() {
        if (V && mShouldCancel) {
            myLogV("shouldCancel: Cancelling");
        }
        
        return mShouldCancel;
    }
    
    // Wi-Fi initiated callbacks (could be executed in another thread)

    /**
     * Called when connected to an AP (this can be the next AP in line, or
     * it can be a completely different network).
     * 
     * @param ssid The SSID of the access point.
     * @param bssid The BSSID of the access point.
     */
    private void onConnected(String ssid, String bssid) {
        if (V) {
            myLogV("onConnected: SSID: " + ssid + ", BSSID: " + bssid);
        }

        /*
         * The current action being processed by the main watchdog thread is now
         * stale, so cancel it.
         */
        cancelCurrentAction();
        
        if ((mSsid == null) || !mSsid.equals(ssid)) {
            /*
             * This is a different network than what the main watchdog thread is
             * processing, dispatch the network change message on the main thread.
             */
            mHandler.dispatchNetworkChanged(ssid);
        }
        
        if (requiresWatchdog(ssid, bssid)) {
            if (D) {
                myLogD(ssid + " (" + bssid + ") requires the watchdog");
            }

            // This access point requires a watchdog, so queue the check on the main thread
            mHandler.checkAp(new AccessPoint(ssid, bssid));
            
        } else {
            if (D) {
                myLogD(ssid + " (" + bssid + ") does not require the watchdog");
            }

            // This access point does not require a watchdog, so queue idle on the main thread
            mHandler.idle();
        }
        if (isWalledGardenTestEnabled()) mHandler.checkWalledGarden(ssid);
    }
    
    /**
     * Called when Wi-Fi is enabled.
     */
    private void onEnabled() {
        cancelCurrentAction();
        // Queue a hard-reset of the state on the main thread
        mHandler.reset();
    }
    
    /**
     * Called when disconnected (or some other event similar to being disconnected).
     */
    private void onDisconnected() {
        if (V) {
            myLogV("onDisconnected");
        }
        
        /*
         * Disconnected from an access point, the action being processed by the
         * watchdog thread is now stale, so cancel it.
         */
        cancelCurrentAction();
        // Dispatch the disconnected to the main watchdog thread
        mHandler.dispatchDisconnected();
        // Queue the action to go idle
        mHandler.idle();
    }

    /**
     * Checks whether an access point requires watchdog monitoring.
     * 
     * @param ssid The SSID of the access point.
     * @param bssid The BSSID of the access point.
     * @return Whether the access point/network should be monitored by the
     *         watchdog.
     */
    private boolean requiresWatchdog(String ssid, String bssid) {
        if (V) {
            myLogV("requiresWatchdog: SSID: " + ssid + ", BSSID: " + bssid);
        }
        
        WifiInfo info = null;
        if (ssid == null) {
            /*
             * This is called from a Wi-Fi callback, so assume the WifiInfo does
             * not have stale data.
             */
            info = mWifiManager.getConnectionInfo();
            ssid = info.getSSID();
            if (ssid == null) {
                // It's still null, give up
                if (V) {
                    Slog.v(TAG, "  Invalid SSID, returning false");
                }
                return false;
            }
        }
        
        if (TextUtils.isEmpty(bssid)) {
            // Similar as above
            if (info == null) {
                info = mWifiManager.getConnectionInfo();
            }
            bssid = info.getBSSID();
            if (TextUtils.isEmpty(bssid)) {
                // It's still null, give up
                if (V) {
                    Slog.v(TAG, "  Invalid BSSID, returning false");
                }
                return false;
            }
        }

        if (!isOnWatchList(ssid)) {
            if (V) {
                Slog.v(TAG, "  SSID not on watch list, returning false");
            }
            return false;
        }

        // The watchdog only monitors networks with multiple APs
        if (!hasRequiredNumberOfAps(ssid)) {
            return false;
        }

        return true;
    }

    private boolean isOnWatchList(String ssid) {
        String watchList;

        if (ssid == null || (watchList = getWatchList()) == null) {
            return false;
        }

        String[] list = watchList.split(" *, *");

        for (String name : list) {
            if (ssid.equals(name)) {
                return true;
            }
        }

        return false;
    }
    
    /**
     * Checks if the current scan results have multiple access points with an SSID.
     * 
     * @param ssid The SSID to check.
     * @return Whether the SSID has multiple access points.
     */
    private boolean hasRequiredNumberOfAps(String ssid) {
        List<ScanResult> results = mWifiManager.getScanResults();
        if (results == null) {
            if (V) {
                myLogV("hasRequiredNumberOfAps: Got null scan results, returning false");
            }
            return false;
        }
        
        int numApsRequired = getApCount();
        int numApsFound = 0;
        int resultsSize = results.size();
        for (int i = 0; i < resultsSize; i++) {
            ScanResult result = results.get(i);
            if (result == null) continue;
            if (result.SSID == null) continue;
            
            if (result.SSID.equals(ssid)) {
                numApsFound++;
                
                if (numApsFound >= numApsRequired) {
                    if (V) {
                        myLogV("hasRequiredNumberOfAps: SSID: " + ssid + ", returning true");
                    }
                    return true;
                }
            }
        }
        
        if (V) {
            myLogV("hasRequiredNumberOfAps: SSID: " + ssid + ", returning false");
        }
        return false;
    }
    
    // Watchdog logic (assume all of these methods will be in our main thread)
    
    /**
     * Handles a Wi-Fi network change (for example, from networkA to networkB).
     */
    private void handleNetworkChanged(String ssid) {
        // Set the SSID being monitored to the new SSID 
        mSsid = ssid;
        // Set various state to that when being idle 
        setIdleState(true);
    }
    
    /**
     * Handles checking whether an AP is a "good" AP.  If not, it will be blacklisted.
     * 
     * @param ap The access point to check.
     */
    private void handleCheckAp(AccessPoint ap) {
        // Reset the cancel state since this is the entry point of this action
        mShouldCancel = false;
        
        if (V) {
            myLogV("handleCheckAp: AccessPoint: " + ap);
        }
        
        // Make sure we are not sleeping
        if (mState == WatchdogState.SLEEP) {
            if (V) {
                Slog.v(TAG, "  Sleeping (in " + mSsid + "), so returning");
            }
            return;
        }
        
        mState = WatchdogState.CHECKING_AP;
        
        /*
         * Checks to make sure we haven't exceeded the max number of checks
         * we're allowed per network
         */
        incrementBssidCheckCount();
        if (getBssidCheckCount() > getMaxApChecks()) {
            if (V) {
                Slog.v(TAG, "  Passed the max attempts (" + getMaxApChecks()
                        + "), going to sleep for " + mSsid);
            }
            mHandler.sleep(mSsid);
            return;
        }

        // Do the check
        boolean isApAlive = checkDnsConnectivity();
        
        if (V) {
            Slog.v(TAG, "  Is it alive: " + isApAlive);
        }

        // Take action based on results
        if (isApAlive) {
            handleApAlive(ap);
        } else {
            handleApUnresponsive(ap);
        }
    }

    /**
     * Handles the case when an access point is alive.
     * 
     * @param ap The access point.
     */
    private void handleApAlive(AccessPoint ap) {
        // Check whether we are stale and should cancel
        if (shouldCancel()) return;
        // We're satisfied with this AP, so go idle
        setIdleState(false);
        
        if (D) {
            myLogD("AP is alive: " + ap.toString());
        }
        
        // Queue the next action to be a background check
        mHandler.backgroundCheckAp(ap);
    }
    
    /**
     * Handles an unresponsive AP by blacklisting it.
     * 
     * @param ap The access point.
     */
    private void handleApUnresponsive(AccessPoint ap) {
        // Check whether we are stale and should cancel
        if (shouldCancel()) return;
        // This AP is "bad", switch to another
        mState = WatchdogState.SWITCHING_AP;

        if (D) {
            myLogD("AP is dead: " + ap.toString());
        }
        
        // Black list this "bad" AP, this will cause an attempt to connect to another
        blacklistAp(ap.bssid);
        // Initiate an association to an alternate AP
        mWifiManager.reassociate();
    }

    private void blacklistAp(String bssid) {
        if (TextUtils.isEmpty(bssid)) {
            return;
        }
        
        // Before taking action, make sure we should not cancel our processing
        if (shouldCancel()) return;
        
        mWifiManager.addToBlacklist(bssid);

        if (D) {
            myLogD("Blacklisting " + bssid);
        }
    }

    /**
     * Handles a single background check. If it fails, it should trigger a
     * normal check. If it succeeds, it should queue another background check.
     * 
     * @param ap The access point to do a background check for. If this is no
     *        longer the current AP, it is okay to return without any
     *        processing.
     */
    private void handleBackgroundCheckAp(AccessPoint ap) {
        // Reset the cancel state since this is the entry point of this action
        mShouldCancel = false;
        
        if (V) {
            myLogV("handleBackgroundCheckAp: AccessPoint: " + ap);
        }
        
        // Make sure we are not sleeping
        if (mState == WatchdogState.SLEEP) {
            if (V) {
                Slog.v(TAG, "  handleBackgroundCheckAp: Sleeping (in " + mSsid + "), so returning");
            }
            return;
        }
        
        // Make sure the AP we're supposed to be background checking is still the active one
        WifiInfo info = mWifiManager.getConnectionInfo();
        if (info.getSSID() == null || !info.getSSID().equals(ap.ssid)) {
            if (V) {
                myLogV("handleBackgroundCheckAp: We are no longer connected to "
                        + ap + ", and instead are on " + info);
            }
            return;
        }
        
        if (info.getBSSID() == null || !info.getBSSID().equals(ap.bssid)) {
            if (V) {
                myLogV("handleBackgroundCheckAp: We are no longer connected to "
                        + ap + ", and instead are on " + info);
            }
            return;
        }

        // Do the check
        boolean isApAlive = backgroundCheckDnsConnectivity();
        
        if (V && !isApAlive) {
            Slog.v(TAG, "  handleBackgroundCheckAp: Is it alive: " + isApAlive);
        }

        if (shouldCancel()) {
            return;
        }
        
        // Take action based on results
        if (isApAlive) {
            // Queue another background check
            mHandler.backgroundCheckAp(ap);
            
        } else {
            if (D) {
                myLogD("Background check failed for " + ap.toString());
            }
            
            // Queue a normal check, so it can take proper action
            mHandler.checkAp(ap);
        }
    }
    
    /**
     * Handles going to sleep for this network. Going to sleep means we will not
     * monitor this network anymore.
     * 
     * @param ssid The network that will not be monitored anymore.
     */
    private void handleSleep(String ssid) {
        // Make sure the network we're trying to sleep in is still the current network
        if (ssid != null && ssid.equals(mSsid)) {
            mState = WatchdogState.SLEEP;

            if (D) {
                myLogD("Going to sleep for " + ssid);
            }
            
            /*
             * Before deciding to go to sleep, we may have checked a few APs
             * (and blacklisted them). Clear the blacklist so the AP with best
             * signal is chosen.
             */
            mWifiManager.clearBlacklist();
            
            if (V) {
                myLogV("handleSleep: Set state to SLEEP and cleared blacklist");
            }
        }
    }

    /**
     * Handles an access point disconnection.
     */
    private void handleDisconnected() {
        /*
         * We purposefully do not change mSsid to null. This is to handle
         * disconnected followed by connected better (even if there is some
         * duration in between). For example, if the watchdog went to sleep in a
         * network, and then the phone goes to sleep, when the phone wakes up we
         * still want to be in the sleeping state. When the phone went to sleep,
         * we would have gotten a disconnected event which would then set mSsid
         * = null. This is bad, since the following connect would cause us to do
         * the "network is good?" check all over again. */
        
        /* 
         * Set the state as if we were idle (don't come out of sleep, only
         * hard reset and network changed should do that.
         */
        setIdleState(false);
    }

    /**
     * Handles going idle. Idle means we are satisfied with the current state of
     * things, but if a new connection occurs we'll re-evaluate.
     */
    private void handleIdle() {
        // Reset the cancel state since this is the entry point for this action
        mShouldCancel = false;
        
        if (V) {
            myLogV("handleSwitchToIdle");
        }
        
        // If we're sleeping, don't do anything
        if (mState == WatchdogState.SLEEP) {
            Slog.v(TAG, "  Sleeping (in " + mSsid + "), so returning");
            return;
        }
        
        // Set the idle state
        setIdleState(false);
        
        if (V) {
            Slog.v(TAG, "  Set state to IDLE");
        }
    }
    
    /**
     * Sets the state as if we are going idle.
     */
    private void setIdleState(boolean forceIdleState) {
        // Setting idle state does not kick us out of sleep unless the forceIdleState is set
        if (forceIdleState || (mState != WatchdogState.SLEEP)) {
            mState = WatchdogState.IDLE;
        }
        resetBssidCheckCount();
    }

    /**
     * Handles a hard reset. A hard reset is rarely used, but when used it
     * should revert anything done by the watchdog monitoring.
     */
    private void handleReset() {
        mWifiManager.clearBlacklist();
        setIdleState(true);
    }
    
    // Inner classes

    /**
     * Possible states for the watchdog to be in.
     */
    private static enum WatchdogState {
        /** The watchdog is currently idle, but it is still responsive to future AP checks in this network. */
        IDLE,
        /** The watchdog is sleeping, so it will not try any AP checks for the network. */
        SLEEP,
        /** The watchdog is currently checking an AP for connectivity. */
        CHECKING_AP,
        /** The watchdog is switching to another AP in the network. */
        SWITCHING_AP
    }

    private int getBssidCheckCount() {
        return mBssidCheckCount;
    }

    private void incrementBssidCheckCount() {
        mBssidCheckCount++;
    }

    private void resetBssidCheckCount() {
        this.mBssidCheckCount = 0;
    }

    /**
     * The main thread for the watchdog monitoring. This will be turned into a
     * {@link Looper} thread.
     */
    private class WifiWatchdogThread extends Thread {
        WifiWatchdogThread() {
            super("WifiWatchdogThread");
        }
        
        @Override
        public void run() {
            // Set this thread up so the handler will work on it
            Looper.prepare();
            
            synchronized(WifiWatchdogService.this) {
                mHandler = new WifiWatchdogHandler();

                // Notify that the handler has been created
                WifiWatchdogService.this.notify();
            }
            
            // Listen for messages to the handler
            Looper.loop();
        }
    }

    /**
     * The main thread's handler. There are 'actions', and just general 
     * 'messages'. There should only ever be one 'action' in the queue (aside
     * from the one being processed, if any). There may be multiple messages in
     * the queue. So, actions are replaced by more recent actions, where as
     * messages will be executed for sure. Messages end up being used to just
     * change some state, and not really take any action.
     * <p>
     * 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 {
        /** Check whether the AP is "good".  The object will be an {@link AccessPoint}. */
        static final int ACTION_CHECK_AP = 1;
        /** Go into the idle state. */
        static final int ACTION_IDLE = 2;
        /**
         * Performs a periodic background check whether the AP is still "good".
         * The object will be an {@link AccessPoint}.
         */
        static final int ACTION_BACKGROUND_CHECK_AP = 3;
        /** Check whether the connection is a walled garden */
        static final int ACTION_CHECK_WALLED_GARDEN = 4;

        /**
         * Go to sleep for the current network. We are conservative with making
         * this a message rather than action. We want to make sure our main
         * thread sees this message, but if it were an action it could be
         * removed from the queue and replaced by another action. The main
         * thread will ensure when it sees the message that the state is still
         * valid for going to sleep.
         * <p>
         * For an explanation of sleep, see {@link android.provider.Settings.Secure#WIFI_WATCHDOG_MAX_AP_CHECKS}.
         */
        static final int MESSAGE_SLEEP = 101;
        /** Disables the watchdog. */
        static final int MESSAGE_DISABLE_WATCHDOG = 102;
        /** The network has changed. */
        static final int MESSAGE_NETWORK_CHANGED = 103;
        /** The current access point has disconnected. */
        static final int MESSAGE_DISCONNECTED = 104;
        /** Performs a hard-reset on the watchdog state. */
        static final int MESSAGE_RESET = 105;

        /* Walled garden detection */
        private String mLastSsid;
        private long mLastTime;
        private final long MIN_WALLED_GARDEN_TEST_INTERVAL = 15 * 60 * 1000; //15 minutes

        void checkWalledGarden(String ssid) {
            sendMessage(obtainMessage(ACTION_CHECK_WALLED_GARDEN, ssid));
        }

        void checkAp(AccessPoint ap) {
            removeAllActions();
            sendMessage(obtainMessage(ACTION_CHECK_AP, ap));
        }
        
        void backgroundCheckAp(AccessPoint ap) {
            if (!isBackgroundCheckEnabled()) return;
            
            removeAllActions();
            sendMessageDelayed(obtainMessage(ACTION_BACKGROUND_CHECK_AP, ap),
                    getBackgroundCheckDelayMs());
        }
        
        void idle() {
            removeAllActions();
            sendMessage(obtainMessage(ACTION_IDLE));
        }
        
        void sleep(String ssid) {
            removeAllActions();
            sendMessage(obtainMessage(MESSAGE_SLEEP, ssid));
        }
        
        void disableWatchdog() {
            removeAllActions();
            sendMessage(obtainMessage(MESSAGE_DISABLE_WATCHDOG));
        }
        
        void dispatchNetworkChanged(String ssid) {
            removeAllActions();
            sendMessage(obtainMessage(MESSAGE_NETWORK_CHANGED, ssid));
        }

        void dispatchDisconnected() {
            removeAllActions();
            sendMessage(obtainMessage(MESSAGE_DISCONNECTED));
        }

        void reset() {
            removeAllActions();
            sendMessage(obtainMessage(MESSAGE_RESET));
        }
        
        private void removeAllActions() {
            removeMessages(ACTION_CHECK_AP);
            removeMessages(ACTION_IDLE);
            removeMessages(ACTION_BACKGROUND_CHECK_AP);
        }
        
        @Override
        public void handleMessage(Message msg) {
            if (V) {
                myLogV("handleMessage: " + msg.what);
            }
            switch (msg.what) {
                case MESSAGE_NETWORK_CHANGED:
                    handleNetworkChanged((String) msg.obj);
                    break;
                case ACTION_CHECK_AP:
                    handleCheckAp((AccessPoint) msg.obj);
                    break;
                case ACTION_BACKGROUND_CHECK_AP:
                    handleBackgroundCheckAp((AccessPoint) msg.obj);
                    break;
                case ACTION_CHECK_WALLED_GARDEN:
                    handleWalledGardenCheck((String) msg.obj);
                    break;
                case MESSAGE_SLEEP:
                    handleSleep((String) msg.obj);
                    break;
                case ACTION_IDLE:
                    handleIdle();
                    break;
                case MESSAGE_DISABLE_WATCHDOG:
                    handleIdle();
                    break;
                case MESSAGE_DISCONNECTED:
                    handleDisconnected();
                    break;
                case MESSAGE_RESET:
                    handleReset();
                    break;
            }
        }

        /**
         * 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();
            }
        }

        private void handleWalledGardenCheck(String ssid) {
            long currentTime = System.currentTimeMillis();
            //Avoid a walled garden test on the same network if one was already done
            //within MIN_WALLED_GARDEN_TEST_INTERVAL. This will handle scenarios where
            //there are frequent network disconnections
            if (ssid.equals(mLastSsid) &&
                    (currentTime - mLastTime) < MIN_WALLED_GARDEN_TEST_INTERVAL) {
                return;
            }

            mLastTime = currentTime;
            mLastSsid = ssid;

            if (isWalledGardenConnection()) {
                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);
            }
        }
    }

    /**
     * Receives Wi-Fi broadcasts.
     * <p>
     * There is little logic in this class, instead methods of the form "on___"
     * are called in the {@link WifiWatchdogService}.
     */
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                handleNetworkStateChanged(
                        (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO));
            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
                handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                        WifiManager.WIFI_STATE_UNKNOWN));
            }
        }

        private void handleNetworkStateChanged(NetworkInfo info) {
            if (V) {
                myLogV("Receiver.handleNetworkStateChanged: NetworkInfo: "
                        + info);
            }
            
            switch (info.getState()) {
                case CONNECTED:
                    WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
                    if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) {
                        if (V) {
                            myLogV("handleNetworkStateChanged: Got connected event but SSID or BSSID are null. SSID: "
                                + wifiInfo.getSSID()
                                + ", BSSID: "
                                + wifiInfo.getBSSID() + ", ignoring event");
                        }
                        return;
                    }
                    onConnected(wifiInfo.getSSID(), wifiInfo.getBSSID());
                    break;

                case DISCONNECTED:
                    onDisconnected();
                    break;
            }
        }

        private void handleWifiStateChanged(int wifiState) {
            if (wifiState == WifiManager.WIFI_STATE_DISABLED) {
                onDisconnected();
            } else if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
                onEnabled();
            }
        }
    };

    /**
     * Describes an access point by its SSID and BSSID.
     *
     */
    private static class AccessPoint {
        String ssid;
        String bssid;
        
        /**
         * @param ssid cannot be null
         * @param bssid cannot be null
         */
        AccessPoint(String ssid, String bssid) {
            if (ssid == null || bssid == null) {
                Slog.e(TAG, String.format("(%s) INVALID ACCESSPOINT: (%s, %s)",
                        Thread.currentThread().getName(),ssid,bssid));
            }
            this.ssid = ssid;
            this.bssid = bssid;
        }
        
        @Override
        public boolean equals(Object o) {
            if (!(o instanceof AccessPoint)) return false;
            AccessPoint otherAp = (AccessPoint) o;

            // Either we both have a null, or our SSIDs and BSSIDs are equal
            return ssid.equals(otherAp.ssid) && bssid.equals(otherAp.bssid);
        }
        
        @Override
        public int hashCode() {
            return ssid.hashCode() + bssid.hashCode();
        }

        @Override
        public String toString() {
            return ssid + " (" + bssid + ")";
        }
    }

    /**
     * Performs a simple DNS "ping" by sending a "server status" query packet to
     * the DNS server. As long as the server replies, we consider it a success.
     * <p>
     * We do not use a simple hostname lookup because that could be cached and
     * the API may not differentiate between a time out and a failure lookup
     * (which we really care about).
     */
    private static class DnsPinger {
        
        /** Number of bytes for the query */
        private static final int DNS_QUERY_BASE_SIZE = 33;
        
        /** The DNS port */
        private static final int DNS_PORT = 53;
        
        /** Used to generate IDs */
        private static Random sRandom = new Random();

        static boolean isDnsReachable(InetAddress dnsAddress, int timeout) {
            DatagramSocket socket = null;
            try {
                socket = new DatagramSocket();

                // Set some socket properties
                socket.setSoTimeout(timeout);

                byte[] buf = new byte[DNS_QUERY_BASE_SIZE];
                fillQuery(buf);

                // Send the DNS query

                DatagramPacket packet = new DatagramPacket(buf,
                        buf.length, dnsAddress, DNS_PORT);
                socket.send(packet);

                // Wait for reply (blocks for the above timeout)
                DatagramPacket replyPacket = new DatagramPacket(buf, buf.length);
                socket.receive(replyPacket);

                // If a timeout occurred, an exception would have been thrown.  We got a reply!
                return true;

            } catch (SocketException e) {
                if (V) {
                    Slog.v(TAG, "DnsPinger.isReachable received SocketException", e);
                }
                return false;

            } catch (UnknownHostException e) {
                if (V) {
                    Slog.v(TAG, "DnsPinger.isReachable is unable to resolve the DNS host", e);
                }
                return false;

            } catch (SocketTimeoutException e) {
                return false;
                
            } catch (IOException e) {
                if (V) {
                    Slog.v(TAG, "DnsPinger.isReachable got an IOException", e);
                }
                return false;
                
            } catch (Exception e) {
                if (V) {
                    Slog.d(TAG, "DnsPinger.isReachable got an unknown exception", e);
                }
                return false;
            } finally {
                if (socket != null) {
                    socket.close();
                }
            }
        }
        
        private static void fillQuery(byte[] buf) {

            /*
             * See RFC2929 (though the bit tables in there are misleading for
             * us. For example, the recursion desired bit is the 0th bit for us,
             * but looking there it would appear as the 7th bit of the byte
             */

            // Make sure it's all zeroed out
            for (int i = 0; i < buf.length; i++) buf[i] = 0;

            // Form a query for www.android.com
            
            // [0-1] bytes are an ID, generate random ID for this query
            buf[0] = (byte) sRandom.nextInt(256); 
            buf[1] = (byte) sRandom.nextInt(256); 
            
            // [2-3] bytes are for flags.
            buf[2] = 1; // Recursion desired

            // [4-5] bytes are for the query count
            buf[5] = 1; // One query 
            
            // [6-7] [8-9] [10-11] are all counts of other fields we don't use

            // [12-15] for www
            writeString(buf, 12, "www");
            
            // [16-23] for android
            writeString(buf, 16, "android");
            
            // [24-27] for com
            writeString(buf, 24, "com");
            
            // [29-30] bytes are for QTYPE, set to 1 
            buf[30] = 1;

            // [31-32] bytes are for QCLASS, set to 1 
            buf[32] = 1;
        }
        
        private static void writeString(byte[] buf, int startPos, String string) {
            int pos = startPos;
            
            // Write the length first
            buf[pos++] = (byte) string.length();
            for (int i = 0; i < string.length(); i++) {
                buf[pos++] = (byte) string.charAt(i);
            }
        }
    }
}
