Watchdog notify on explicit connect

Notifies when user explicitly clicks on wifi dialog.

Change-Id: I5eee37d68b422d748d41e9384d5006482a223dc5
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9a4e0fc..1ecdfce 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3042,7 +3042,7 @@
 
         /**
          * Boolean to determine whether to notify on disabling a network.  Secure setting used
-         * to notify user only once.  This setting is not monitored continuously.
+         * to notify user only once.
          * @hide
          */
         public static final String WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP =
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index afd8908..aa4387e5 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2583,10 +2583,10 @@
         <item quantity="other">Open Wi-Fi networks available</item>
     </plurals>
 
-     <!-- A notification is shown the first time a wireless network is disabled due to bad connectivity.  This is the notification's title / ticker. -->
-    <string name="wifi_watchdog_network_disabled">A Wi-Fi network was disabled</string>
-    <!--  A notification is shown the first time a wireless network is disabled due to bad connectivity.  This is the notification's message which leads to the settings pane -->
-    <string name="wifi_watchdog_network_disabled_detailed">A Wi-Fi network was temporarily disabled due to bad connectivity.</string>
+     <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is the notification's title / ticker. -->
+     <string name="wifi_watchdog_network_disabled">Couldn\'t connect to Wi-Fi</string>
+     <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is a partial string of the message, which will also include the (possibly truncated) hotspot name. -->
+    <string name="wifi_watchdog_network_disabled_detailed"> has a poor internet connection.</string>
 
     <!-- Do not translate. Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 242a93d..a80a2b8 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -289,6 +289,10 @@
                     mWifiStateMachine.startWps(msg.replyTo, (WpsConfiguration)msg.obj);
                     break;
                 }
+                case WifiManager.CMD_DISABLE_NETWORK: {
+                    mWifiStateMachine.disableNetwork(msg.replyTo, msg.arg1, msg.arg2);
+                    break;
+                }
                 default: {
                     Slog.d(TAG, "WifiServicehandler.handleMessage ignoring msg=" + msg);
                     break;
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index 9168e62..cbd284c 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -89,7 +89,7 @@
             mNetworksDisabledDuringConnect = false;
         }
         /* Disable failed network */
-        WifiConfigStore.disableNetwork(netId);
+        WifiConfigStore.disableNetwork(netId, WifiConfiguration.DISABLED_AUTH_FAILURE);
     }
 
     private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) {
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index d83b968..9a51d5e 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -195,8 +195,9 @@
      * or a failure event from supplicant
      *
      * @param config The configuration details in WifiConfiguration
+     * @return the networkId now associated with the specified configuration
      */
-    static void selectNetwork(WifiConfiguration config) {
+    static int selectNetwork(WifiConfiguration config) {
         if (config != null) {
             NetworkUpdateResult result = addOrUpdateNetworkNative(config);
             int netId = result.getNetworkId();
@@ -205,7 +206,9 @@
             } else {
                 Log.e(TAG, "Failed to update network " + config);
             }
+            return netId;
         }
+        return INVALID_NETWORK_ID;
     }
 
     /**
@@ -351,10 +354,22 @@
      * @param netId network to be disabled
      */
     static boolean disableNetwork(int netId) {
+        return disableNetwork(netId, WifiConfiguration.DISABLED_UNKNOWN_REASON);
+    }
+
+    /**
+     * Disable a network. Note that there is no saveConfig operation.
+     * @param netId network to be disabled
+     * @param reason reason code network was disabled
+     */
+    static boolean disableNetwork(int netId, int reason) {
         boolean ret = WifiNative.disableNetworkCommand(netId);
         synchronized (sConfiguredNetworks) {
             WifiConfiguration config = sConfiguredNetworks.get(netId);
-            if (config != null) config.status = Status.DISABLED;
+            if (config != null) {
+                config.status = Status.DISABLED;
+                config.disableReason = reason;
+            }
         }
         sendConfiguredNetworksChangedBroadcast();
         return ret;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 28a5bc6..d2a0b30 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -211,6 +211,15 @@
         public static final String[] strings = { "current", "disabled", "enabled" };
     }
 
+    /** @hide */
+    public static final int DISABLED_UNKNOWN_REASON                         = 0;
+    /** @hide */
+    public static final int DISABLED_DNS_FAILURE                            = 1;
+    /** @hide */
+    public static final int DISABLED_DHCP_FAILURE                           = 2;
+    /** @hide */
+    public static final int DISABLED_AUTH_FAILURE                           = 3;
+
     /**
      * The ID number that the supplicant uses to identify this
      * network configuration entry. This must be passed as an argument
@@ -223,6 +232,14 @@
      * @see Status
      */
     public int status;
+
+    /**
+     * The code referring to a reason for disabling the network
+     * Valid when {@link #status} == Status.DISABLED
+     * @hide
+     */
+    public int disableReason;
+
     /**
      * The network's SSID. Can either be an ASCII string,
      * which must be enclosed in double quotation marks
@@ -351,6 +368,7 @@
         BSSID = null;
         priority = 0;
         hiddenSSID = false;
+        disableReason = DISABLED_UNKNOWN_REASON;
         allowedKeyManagement = new BitSet();
         allowedProtocols = new BitSet();
         allowedAuthAlgorithms = new BitSet();
@@ -367,12 +385,13 @@
         linkProperties = new LinkProperties();
     }
 
+    @Override
     public String toString() {
-        StringBuffer sbuf = new StringBuffer();
+        StringBuilder sbuf = new StringBuilder();
         if (this.status == WifiConfiguration.Status.CURRENT) {
             sbuf.append("* ");
         } else if (this.status == WifiConfiguration.Status.DISABLED) {
-            sbuf.append("- ");
+            sbuf.append("- DSBLE: ").append(this.disableReason).append(" ");
         }
         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
                 append(" BSSID: ").append(this.BSSID).append(" PRIO: ").append(this.priority).
@@ -541,6 +560,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(networkId);
         dest.writeInt(status);
+        dest.writeInt(disableReason);
         dest.writeString(SSID);
         dest.writeString(BSSID);
         dest.writeString(preSharedKey);
@@ -571,6 +591,7 @@
                 WifiConfiguration config = new WifiConfiguration();
                 config.networkId = in.readInt();
                 config.status = in.readInt();
+                config.disableReason = in.readInt();
                 config.SSID = in.readString();
                 config.BSSID = in.readString();
                 config.preSharedKey = in.readString();
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 7bb927b..d5b404e 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -70,6 +70,7 @@
     private InetAddress mIpAddress;
 
     private String mMacAddress;
+    private boolean mExplicitConnect;
 
     WifiInfo() {
         mSSID = null;
@@ -79,6 +80,7 @@
         mRssi = -9999;
         mLinkSpeed = -1;
         mHiddenSSID = false;
+        mExplicitConnect = false;
     }
 
     /**
@@ -96,6 +98,7 @@
             mLinkSpeed = source.mLinkSpeed;
             mIpAddress = source.mIpAddress;
             mMacAddress = source.mMacAddress;
+            mExplicitConnect = source.mExplicitConnect;
         }
     }
 
@@ -172,6 +175,22 @@
         mNetworkId = id;
     }
 
+
+    /**
+     * @hide
+     */
+    public boolean isExplicitConnect() {
+        return mExplicitConnect;
+    }
+
+    /**
+     * @hide
+     */
+    public void setExplicitConnect(boolean explicitConnect) {
+        this.mExplicitConnect = explicitConnect;
+    }
+
+
     /**
      * Each configured network has a unique small integer ID, used to identify
      * the network when performing operations on the supplicant. This method
@@ -260,7 +279,8 @@
             append(mSupplicantState == null ? none : mSupplicantState).
             append(", RSSI: ").append(mRssi).
             append(", Link speed: ").append(mLinkSpeed).
-            append(", Net ID: ").append(mNetworkId);
+            append(", Net ID: ").append(mNetworkId).
+            append(", Explicit connect: ").append(mExplicitConnect);
 
         return sb.toString();
     }
@@ -284,6 +304,7 @@
         dest.writeString(getSSID());
         dest.writeString(mBSSID);
         dest.writeString(mMacAddress);
+        dest.writeByte(mExplicitConnect ? (byte)1 : (byte)0);
         mSupplicantState.writeToParcel(dest, flags);
     }
 
@@ -303,6 +324,7 @@
                 info.setSSID(in.readString());
                 info.mBSSID = in.readString();
                 info.mMacAddress = in.readString();
+                info.mExplicitConnect = in.readByte() == 1 ? true : false;
                 info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
                 return info;
             }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index cd6621f..5f8385c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -615,6 +615,17 @@
     }
 
     /**
+     * Disable a configured network asynchronously.  This call is for abnormal network
+     * events, and the user may be notified of network change, if they recently attempted
+     * to connect to the specified network.
+     * @param netId the ID of the network as returned by {@link #addNetwork}.
+     * @hide
+     */
+    public void disableNetwork(int netId, int reason) {
+        mAsyncChannel.sendMessage(CMD_DISABLE_NETWORK, netId, reason);
+    }
+
+    /**
      * Disassociate from the currently active access point. This may result
      * in the asynchronous delivery of state change events.
      * @return {@code true} if the operation succeeded
@@ -1058,6 +1069,8 @@
     public static final int CMD_SAVE_NETWORK                = 3;
     /** @hide */
     public static final int CMD_START_WPS                   = 4;
+    /** @hide */
+    public static final int CMD_DISABLE_NETWORK             = 5;
 
     /* Events from WifiService */
     /** @hide */
@@ -1617,4 +1630,4 @@
              return false;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 331d5c0..82ff0de 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -68,12 +68,14 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.LruCache;
+import android.util.Slog;
 
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.AsyncChannel;
@@ -482,6 +484,11 @@
     private final WorkSource mLastRunningWifiUids = new WorkSource();
 
     private final IBatteryStats mBatteryStats;
+    private boolean mNextWifiActionExplicit = false;
+    private int mLastExplicitNetworkId;
+    private long mLastNetworkChoiceTime;
+    private static final long EXPLICIT_CONNECT_ALLOWED_DELAY_MS = 2 * 60 * 1000;
+
 
     public WifiStateMachine(Context context, String wlanInterface) {
         super(TAG);
@@ -821,7 +828,8 @@
      * @return {@code true} if the operation succeeds, {@code false} otherwise
      */
     public boolean syncDisableNetwork(AsyncChannel channel, int netId) {
-        Message resultMsg = channel.sendMessageSynchronously(CMD_DISABLE_NETWORK, netId);
+        Message resultMsg = channel.sendMessageSynchronously(CMD_DISABLE_NETWORK, netId,
+                WifiConfiguration.DISABLED_UNKNOWN_REASON);
         boolean result = (resultMsg.arg1 != FAILURE);
         resultMsg.recycle();
         return result;
@@ -866,6 +874,12 @@
         sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0));
     }
 
+    public void disableNetwork(Messenger replyTo, int netId, int reason) {
+        Message message = obtainMessage(CMD_DISABLE_NETWORK, netId, reason);
+        message.replyTo = replyTo;
+        sendMessage(message);
+    }
+
     public void startWps(Messenger replyTo, WpsConfiguration config) {
         Message msg = obtainMessage(CMD_START_WPS, config);
         msg.replyTo = replyTo;
@@ -1534,6 +1548,7 @@
         mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
         mWifiInfo.setRssi(MIN_RSSI);
         mWifiInfo.setLinkSpeed(-1);
+        mWifiInfo.setExplicitConnect(false);
 
         /* send event to CM & network change broadcast */
         setNetworkDetailedState(DetailedState.DISCONNECTED);
@@ -1631,7 +1646,8 @@
         if (++mReconnectCount > getMaxDhcpRetries()) {
             Log.e(TAG, "Failed " +
                     mReconnectCount + " times, Disabling " + mLastNetworkId);
-            WifiConfigStore.disableNetwork(mLastNetworkId);
+            WifiConfigStore.disableNetwork(mLastNetworkId,
+                    WifiConfiguration.DISABLED_DHCP_FAILURE);
             mReconnectCount = 0;
         }
 
@@ -2169,7 +2185,7 @@
                     WifiConfigStore.enableAllNetworks();
                     break;
                 case CMD_DISABLE_NETWORK:
-                    ok = WifiConfigStore.disableNetwork(message.arg1);
+                    ok = WifiConfigStore.disableNetwork(message.arg1, message.arg2);
                     mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
                     break;
                 case CMD_BLACKLIST_NETWORK:
@@ -2605,7 +2621,7 @@
                      * a connection to the enabled network.
                      */
                     if (config != null) {
-                        WifiConfigStore.selectNetwork(config);
+                        netId = WifiConfigStore.selectNetwork(config);
                     } else {
                         WifiConfigStore.selectNetwork(netId);
                     }
@@ -2614,7 +2630,10 @@
                     mSupplicantStateTracker.sendMessage(CMD_CONNECT_NETWORK);
 
                     WifiNative.reconnectCommand();
-
+                    mLastExplicitNetworkId = netId;
+                    mLastNetworkChoiceTime  = SystemClock.elapsedRealtime();
+                    mNextWifiActionExplicit = true;
+                    Slog.d(TAG, "Setting wifi connect explicit for netid " + netId);
                     /* Expect a disconnection from the old connection */
                     transitionTo(mDisconnectingState);
                     break;
@@ -2636,6 +2655,13 @@
                     mWifiInfo.setSSID(fetchSSID());
                     mWifiInfo.setBSSID(mLastBssid);
                     mWifiInfo.setNetworkId(mLastNetworkId);
+                    if (mNextWifiActionExplicit &&
+                        mWifiInfo.getNetworkId() == mLastExplicitNetworkId &&
+                        SystemClock.elapsedRealtime() < mLastNetworkChoiceTime +
+                                                            EXPLICIT_CONNECT_ALLOWED_DELAY_MS) {
+                        mWifiInfo.setExplicitConnect(true);
+                    }
+                    mNextWifiActionExplicit = false;
                     /* send event to CM & network change broadcast */
                     setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
                     sendNetworkStateChangeBroadcast(mLastBssid);
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index 168c68b..5c8926c 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -70,6 +70,7 @@
     private static final boolean VDBG = false;
     private static final boolean DBG = true;
     private static final String WWSM_TAG = "WifiWatchdogStateMachine";
+    private static final String WATCHDOG_NOTIFICATION_ID = "Android.System.WifiWatchdog";
 
     private static final int WIFI_SIGNAL_LEVELS = 4;
     /**
@@ -157,7 +158,7 @@
     /**
      * The {@link WifiInfo} object passed to WWSM on network broadcasts
      */
-    private WifiInfo mInitialConnInfo;
+    private WifiInfo mConnectionInfo;
     private int mNetEventCounter = 0;
 
     /**
@@ -173,7 +174,9 @@
      * It triggers a disableNetwork call if a DNS check fails.
      */
     public boolean mDisableAPNextFailure = false;
-    public ConnectivityManager mConnectivityManager;
+    private ConnectivityManager mConnectivityManager;
+    private boolean mNotificationShown;
+    public boolean mHasConnectedWifiManager = false;
 
     /**
      * STATE MAP
@@ -212,8 +215,6 @@
 
         setInitialState(mWatchdogDisabledState);
         updateSettings();
-        mShowDisabledNotification = getSettingsBoolean(mContentResolver,
-                Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, true);
     }
 
     public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) {
@@ -318,6 +319,9 @@
         mContext.getContentResolver().registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL),
                 false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP)
+                , false, contentObserver);
     }
 
     /**
@@ -356,7 +360,7 @@
     public void dump(PrintWriter pw) {
         pw.print("WatchdogStatus: ");
         pw.print("State " + getCurrentState());
-        pw.println(", network [" + mInitialConnInfo + "]");
+        pw.println(", network [" + mConnectionInfo + "]");
         pw.print("checkFailures   " + mNumCheckFailures);
         pw.println(", bssids: " + mBssids);
         pw.println("lastSingleCheck: " + mOnlineWatchState.lastCheckTime);
@@ -396,6 +400,8 @@
         mWalledGardenIntervalMs = Secure.getLong(mContentResolver,
                 Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS,
                 DEFAULT_WALLED_GARDEN_INTERVAL_MS);
+        mShowDisabledNotification = getSettingsBoolean(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, true);
     }
 
     /**
@@ -420,17 +426,42 @@
     }
 
     /**
-   *
-   */
+     * Uses {@link #mConnectionInfo}.
+     */
+    private void updateBssids() {
+        String curSsid = mConnectionInfo.getSSID();
+        List<ScanResult> results = mWifiManager.getScanResults();
+        int oldNumBssids = mBssids.size();
+
+        if (results == null) {
+            if (DBG) {
+                Slog.d(WWSM_TAG, "updateBssids: Got null scan results!");
+            }
+            return;
+        }
+
+        for (ScanResult result : results) {
+            if (result == null || result.SSID == null) {
+                if (DBG) {
+                    Slog.d(WWSM_TAG, "Received invalid scan result: " + result);
+                }
+                continue;
+            }
+            if (curSsid.equals(result.SSID))
+                mBssids.add(result.BSSID);
+        }
+    }
+
     private void resetWatchdogState() {
         if (VDBG) {
             Slog.v(WWSM_TAG, "Resetting watchdog state...");
         }
-        mInitialConnInfo = null;
+        mConnectionInfo = null;
         mDisableAPNextFailure = false;
         mLastWalledGardenCheckTime = null;
         mNumCheckFailures = 0;
         mBssids.clear();
+        cancelNetworkNotification();
     }
 
     private void popUpBrowser() {
@@ -441,11 +472,11 @@
         mContext.startActivity(intent);
     }
 
-    private void displayDisabledNetworkNotification() {
+    private void displayDisabledNetworkNotification(String ssid) {
         Resources r = Resources.getSystem();
         CharSequence title =
                 r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled);
-        CharSequence msg =
+        String msg = ssid +
                 r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled_detailed);
 
         Notification wifiDisabledWarning = new Notification.Builder(mContext)
@@ -455,7 +486,7 @@
             .setContentTitle(title)
             .setContentText(msg)
             .setContentIntent(PendingIntent.getActivity(mContext, 0,
-                    new Intent(Settings.ACTION_WIFI_IP_SETTINGS)
+                    new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK)
                         .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0))
             .setWhen(System.currentTimeMillis())
             .setAutoCancel(true)
@@ -464,7 +495,17 @@
         NotificationManager notificationManager = (NotificationManager) mContext
                 .getSystemService(Context.NOTIFICATION_SERVICE);
 
-        notificationManager.notify("WifiWatchdog", wifiDisabledWarning.icon, wifiDisabledWarning);
+        notificationManager.notify(WATCHDOG_NOTIFICATION_ID, 1, wifiDisabledWarning);
+        mNotificationShown = true;
+    }
+
+    public void cancelNetworkNotification() {
+        if (mNotificationShown) {
+            NotificationManager notificationManager = (NotificationManager) mContext
+                    .getSystemService(Context.NOTIFICATION_SERVICE);
+            notificationManager.cancel(WATCHDOG_NOTIFICATION_ID, 1);
+            mNotificationShown = false;
+        }
     }
 
     /**
@@ -537,6 +578,7 @@
 
                     switch (networkInfo.getState()) {
                         case CONNECTED:
+                            cancelNetworkNotification();
                             WifiInfo wifiInfo = (WifiInfo)
                                 stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
                             if (wifiInfo == null) {
@@ -551,6 +593,8 @@
                             }
 
                             initConnection(wifiInfo);
+                            mConnectionInfo = wifiInfo;
+                            updateBssids();
                             transitionTo(mDnsCheckingState);
                             mNetEventCounter++;
                             return HANDLED;
@@ -579,16 +623,15 @@
          */
         private void initConnection(WifiInfo wifiInfo) {
             if (VDBG) {
-                Slog.v(WWSM_TAG, "Connected:: old " + wifiInfoToStr(mInitialConnInfo) +
+                Slog.v(WWSM_TAG, "Connected:: old " + wifiInfoToStr(mConnectionInfo) +
                         " ==> new " + wifiInfoToStr(wifiInfo));
             }
 
-            if (mInitialConnInfo == null || !wifiInfo.getSSID().equals(mInitialConnInfo.getSSID())) {
+            if (mConnectionInfo == null || !wifiInfo.getSSID().equals(mConnectionInfo.getSSID())) {
                 resetWatchdogState();
-            } else if (!wifiInfo.getBSSID().equals(mInitialConnInfo.getBSSID())) {
+            } else if (!wifiInfo.getBSSID().equals(mConnectionInfo.getBSSID())) {
                 mDisableAPNextFailure = false;
             }
-            mInitialConnInfo = wifiInfo;
         }
 
         @Override
@@ -606,27 +649,7 @@
         public boolean processMessage(Message msg) {
             switch (msg.what) {
                 case EVENT_SCAN_RESULTS_AVAILABLE:
-                    String curSsid = mInitialConnInfo.getSSID();
-                    List<ScanResult> results = mWifiManager.getScanResults();
-                    int oldNumBssids = mBssids.size();
-
-                    if (results == null) {
-                        if (DBG) {
-                            Slog.d(WWSM_TAG, "updateBssids: Got null scan results!");
-                        }
-                        return HANDLED;
-                    }
-
-                    for (ScanResult result : results) {
-                        if (result == null || result.SSID == null) {
-                            if (VDBG) {
-                                Slog.v(WWSM_TAG, "Received invalid scan result: " + result);
-                            }
-                            continue;
-                        }
-                        if (curSsid.equals(result.SSID))
-                            mBssids.add(result.BSSID);
-                    }
+                    updateBssids();
                     return HANDLED;
                 case EVENT_WATCHDOG_SETTINGS_CHANGE:
                     // Stop current checks, but let state update
@@ -635,7 +658,6 @@
             }
             return NOT_HANDLED;
         }
-
     }
 
     class DnsCheckingState extends State {
@@ -653,7 +675,7 @@
             if (DBG) {
                 Slog.d(WWSM_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime());
                 dnsCheckLogStr = String.format("Pinging %s on ssid [%s]: ",
-                        dns, mInitialConnInfo.getSSID());
+                        mDnsPinger.getDns(), mConnectionInfo.getSSID());
             }
 
             for (int i=0; i < mNumDnsPings; i++) {
@@ -905,7 +927,8 @@
                 return HANDLED;
             }
 
-            if (mDisableAPNextFailure || mNumCheckFailures >= mMaxSsidBlacklists) {
+            if (mDisableAPNextFailure || mNumCheckFailures >= mBssids.size()
+                    || mNumCheckFailures >= mMaxSsidBlacklists) {
                 if (hasNoMobileData()) {
                     Slog.w(WWSM_TAG, "Would disable bad network, but device has no mobile data!" +
                             "  Going idle...");
@@ -913,23 +936,26 @@
                     transitionTo(mNotConnectedState);
                     return HANDLED;
                 }
+
                 // TODO : Unban networks if they had low signal ?
-                Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mInitialConnInfo)
+                Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mConnectionInfo)
                         + ".  " + "numCheckFailures " + mNumCheckFailures
                         + ", numAPs " + mBssids.size());
-                mWifiManager.disableNetwork(mInitialConnInfo.getNetworkId());
-                if (mShowDisabledNotification) {
-                    displayDisabledNetworkNotification();
-                    mShowDisabledNotification = false;
-                    putSettingsBoolean(mContentResolver,
-                            Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, false);
+                int networkId = mConnectionInfo.getNetworkId();
+                if (!mHasConnectedWifiManager) {
+                    mWifiManager.asyncConnect(mContext, getHandler());
+                    mHasConnectedWifiManager = true;
+                }
+                mWifiManager.disableNetwork(networkId, WifiConfiguration.DISABLED_DNS_FAILURE);
+                if (mShowDisabledNotification && mConnectionInfo.isExplicitConnect()) {
+                    displayDisabledNetworkNotification(mConnectionInfo.getSSID());
                 }
                 transitionTo(mNotConnectedState);
             } else {
-                Slog.i(WWSM_TAG, "Blacklisting current BSSID.  " + wifiInfoToStr(mInitialConnInfo)
+                Slog.i(WWSM_TAG, "Blacklisting current BSSID.  " + wifiInfoToStr(mConnectionInfo)
                        + "numCheckFailures " + mNumCheckFailures + ", numAPs " + mBssids.size());
 
-                mWifiManager.addToBlacklist(mInitialConnInfo.getBSSID());
+                mWifiManager.addToBlacklist(mConnectionInfo.getBSSID());
                 mWifiManager.reassociate();
                 transitionTo(mBlacklistedApState);
             }