Add new states to support wpa_supplicant 0.8

Latest supplicant introduces the INTERFACE_DISABLED state. This
is entered when the interface is brought down (which is effectively
done by us and tracked already through the driver stop operation)

Also, added is a state for tracking authentication when supplicant acts as
the SME

Change-Id: I76090068d0ebba6df76f16707da559fcbd7512c5
diff --git a/api/current.txt b/api/current.txt
index 3a90ef7..8ea9ebd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11596,12 +11596,14 @@
     method public void writeToParcel(android.os.Parcel, int);
     enum_constant public static final android.net.wifi.SupplicantState ASSOCIATED;
     enum_constant public static final android.net.wifi.SupplicantState ASSOCIATING;
+    enum_constant public static final android.net.wifi.SupplicantState AUTHENTICATING;
     enum_constant public static final android.net.wifi.SupplicantState COMPLETED;
     enum_constant public static final android.net.wifi.SupplicantState DISCONNECTED;
     enum_constant public static final android.net.wifi.SupplicantState DORMANT;
     enum_constant public static final android.net.wifi.SupplicantState FOUR_WAY_HANDSHAKE;
     enum_constant public static final android.net.wifi.SupplicantState GROUP_HANDSHAKE;
     enum_constant public static final android.net.wifi.SupplicantState INACTIVE;
+    enum_constant public static final android.net.wifi.SupplicantState INTERFACE_DISABLED;
     enum_constant public static final android.net.wifi.SupplicantState INVALID;
     enum_constant public static final android.net.wifi.SupplicantState SCANNING;
     enum_constant public static final android.net.wifi.SupplicantState UNINITIALIZED;
diff --git a/wifi/java/android/net/wifi/SupplicantState.java b/wifi/java/android/net/wifi/SupplicantState.java
index 6b79210..91e685f 100644
--- a/wifi/java/android/net/wifi/SupplicantState.java
+++ b/wifi/java/android/net/wifi/SupplicantState.java
@@ -39,6 +39,15 @@
     DISCONNECTED,
 
     /**
+     * Interface is disabled
+     * <p/>
+     * This state is entered if the network interface is disabled.
+     * wpa_supplicant refuses any new operations that would
+     * use the radio until the interface has been enabled.
+     */
+    INTERFACE_DISABLED,
+
+    /**
      * Inactive state (wpa_supplicant disabled).
      * <p/>
      * This state is entered if there are no enabled networks in the
@@ -57,6 +66,15 @@
     SCANNING,
 
     /**
+     * Trying to authenticate with a BSS/SSID
+     * <p/>
+     * This state is entered when wpa_supplicant has found a suitable BSS
+     * to authenticate with and the driver is configured to try to
+     * authenticate with this BSS.
+     */
+    AUTHENTICATING,
+
+    /**
      * Trying to associate with a BSS/SSID.
      * <p/>
      * This state is entered when wpa_supplicant has found a suitable BSS
@@ -152,8 +170,33 @@
         return state != UNINITIALIZED && state != INVALID;
     }
 
+
+    /* Supplicant associating or authenticating is considered a handshake state */
+    static boolean isHandshakeState(SupplicantState state) {
+        switch(state) {
+            case AUTHENTICATING:
+            case ASSOCIATING:
+            case ASSOCIATED:
+            case FOUR_WAY_HANDSHAKE:
+            case GROUP_HANDSHAKE:
+                return true;
+            case COMPLETED:
+            case DISCONNECTED:
+            case INTERFACE_DISABLED:
+            case INACTIVE:
+            case SCANNING:
+            case DORMANT:
+            case UNINITIALIZED:
+            case INVALID:
+                return false;
+            default:
+                throw new IllegalArgumentException("Unknown supplicant state");
+        }
+    }
+
     static boolean isConnecting(SupplicantState state) {
         switch(state) {
+            case AUTHENTICATING:
             case ASSOCIATING:
             case ASSOCIATED:
             case FOUR_WAY_HANDSHAKE:
@@ -161,6 +204,7 @@
             case COMPLETED:
                 return true;
             case DISCONNECTED:
+            case INTERFACE_DISABLED:
             case INACTIVE:
             case SCANNING:
             case DORMANT:
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index 9ae26da..0c4f9f6 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -98,12 +98,16 @@
         if (DBG) Log.d(TAG, "Supplicant state: " + supState.toString() + "\n");
 
         switch (supState) {
-            case DISCONNECTED:
+           case DISCONNECTED:
                 transitionTo(mDisconnectState);
                 break;
+            case INTERFACE_DISABLED:
+                //we should have received a disconnection already, do nothing
+                break;
             case SCANNING:
                 transitionTo(mScanState);
                 break;
+            case AUTHENTICATING:
             case ASSOCIATING:
             case ASSOCIATED:
             case FOUR_WAY_HANDSHAKE:
@@ -250,10 +254,7 @@
                 case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                     SupplicantState state = stateChangeResult.state;
-                    if (state == SupplicantState.ASSOCIATING ||
-                            state == SupplicantState.ASSOCIATED ||
-                            state == SupplicantState.FOUR_WAY_HANDSHAKE ||
-                            state == SupplicantState.GROUP_HANDSHAKE) {
+                    if (SupplicantState.isHandshakeState(state)) {
                         if (mLoopDetectIndex > state.ordinal()) {
                             mLoopDetectCount++;
                         }
@@ -296,12 +297,11 @@
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                     SupplicantState state = stateChangeResult.state;
                     sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
-                    /* Ignore a re-auth in completed state */
-                    if (state == SupplicantState.ASSOCIATING ||
-                            state == SupplicantState.ASSOCIATED ||
-                            state == SupplicantState.FOUR_WAY_HANDSHAKE ||
-                            state == SupplicantState.GROUP_HANDSHAKE ||
-                            state == SupplicantState.COMPLETED) {
+                    /* Ignore any connecting state in completed state. Group re-keying
+                     * events and other auth events that do not affect connectivity are
+                     * ignored
+                     */
+                    if (SupplicantState.isConnecting(state)) {
                         break;
                     }
                     transitionOnSupplicantStateChange(stateChangeResult);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index f60ae48..e3661bf 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -41,8 +41,10 @@
 
     static {
         stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
+        stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
         stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE);
         stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING);
+        stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING);
         stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING);
         stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING);
         stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING);