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

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Random;

/**
 * {@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 || Config.LOGV;
    private static final boolean D = true || Config.LOGD;
    
    private Context mContext;
    private ContentResolver mContentResolver;
    private WifiManager mWifiManager;
    
    /**
     * 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!
     */
    private int mNumApsChecked;
    /** 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_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 DNS of the current AP.
     * 
     * @return The DNS of the current AP.
     */
    private int getDns() {
        DhcpInfo addressInfo = mWifiManager.getDhcpInfo();
        if (addressInfo != null) {
            return addressInfo.dns1;
        } else {
            return -1;
        }
    }
    
    /**
     * 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() {
        int dns = getDns();
        if (dns == -1) {
            if (V) {
                myLogV("checkDnsConnectivity: Invalid DNS, returning false");
            }
            return false;
        }
        
        if (V) {
            myLogV("checkDnsConnectivity: Checking 0x" +
                    Integer.toHexString(Integer.reverseBytes(dns)) + " 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.
                 */
                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);
            }
        }
        
        int packetLossPercentage = 100 * (numPings - successCounter) / numPings;
        if (D) {
            Slog.d(TAG, packetLossPercentage
                    + "% packet loss (acceptable is " + acceptableLoss + "%)");
        }
        
        return !shouldCancel() && (packetLossPercentage <= acceptableLoss);
    }

    private boolean backgroundCheckDnsConnectivity() {
        int dns = getDns();
        if (false && V) {
            myLogV("backgroundCheckDnsConnectivity: Background checking " + dns +
                    " for connectivity");
        }
        
        if (dns == -1) {
            if (V) {
                myLogV("backgroundCheckDnsConnectivity: DNS is empty, returning false");
            }
            return false;
        }
        
        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();
        }
    }
    
    /**
     * 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
         */
        mNumApsChecked++;
        if (mNumApsChecked > 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 (false && 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;
        }
        mNumApsChecked = 0;
    }

    /**
     * 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
    }

    /**
     * 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;

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

    /**
     * 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;
        
        AccessPoint(String ssid, String bssid) {
            this.ssid = ssid;
            this.bssid = bssid;
        }

        private boolean hasNull() {
            return ssid == null || bssid == null;
        }
        
        @Override
        public boolean equals(Object o) {
            if (!(o instanceof AccessPoint)) return false;
            AccessPoint otherAp = (AccessPoint) o;
            boolean iHaveNull = hasNull();
            // Either we both have a null, or our SSIDs and BSSIDs are equal
            return (iHaveNull && otherAp.hasNull()) || 
                    (otherAp.bssid != null && ssid.equals(otherAp.ssid)
                    && bssid.equals(otherAp.bssid));
        }
        
        @Override
        public int hashCode() {
            if (ssid == null || bssid == null) return 0;
            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(int dns, 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
                byte parts[] = new byte[4];
                parts[0] = (byte)(dns & 0xff);
                parts[1] = (byte)((dns >> 8) & 0xff);
                parts[2] = (byte)((dns >> 16) & 0xff);
                parts[3] = (byte)((dns >> 24) & 0xff);

                InetAddress dnsAddress = InetAddress.getByAddress(parts);
                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 || Config.LOGD) {
                    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);
            }
        }
    }
}
