fix network disconnection handling

We should avoid network id set unless the access point is associating.
Also, we should reset network connection state before sending
out network change broadcast.

Finally, we should reset connect mode settings when we disconnect from
an access point

Bug: 3424635
Change-Id: I41db5399810218abd6a77155166db5a9b1dbd22c
diff --git a/wifi/java/android/net/wifi/SupplicantState.java b/wifi/java/android/net/wifi/SupplicantState.java
index 169b2d6..6b79210 100644
--- a/wifi/java/android/net/wifi/SupplicantState.java
+++ b/wifi/java/android/net/wifi/SupplicantState.java
@@ -152,6 +152,26 @@
         return state != UNINITIALIZED && state != INVALID;
     }
 
+    static boolean isConnecting(SupplicantState state) {
+        switch(state) {
+            case ASSOCIATING:
+            case ASSOCIATED:
+            case FOUR_WAY_HANDSHAKE:
+            case GROUP_HANDSHAKE:
+            case COMPLETED:
+                return true;
+            case DISCONNECTED:
+            case INACTIVE:
+            case SCANNING:
+            case DORMANT:
+            case UNINITIALIZED:
+            case INVALID:
+                return false;
+            default:
+                throw new IllegalArgumentException("Unknown supplicant state");
+        }
+    }
+
     /** Implement the Parcelable interface {@hide} */
     public int describeContents() {
         return 0;
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index d6f8e51..bb2f277 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -344,6 +344,9 @@
      */
     private static final long DEFAULT_SCAN_INTERVAL_MS = 60 * 1000; /* 1 minute */
 
+    private static final int MIN_RSSI = -200;
+    private static final int MAX_RSSI = 256;
+
     /* Default parent state */
     private HierarchicalState mDefaultState = new DefaultState();
     /* Temporary initial state */
@@ -1238,7 +1241,7 @@
      */
     private void fetchRssiAndLinkSpeedNative() {
         int newRssi = WifiNative.getRssiCommand();
-        if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values
+        if (newRssi != -1 && MIN_RSSI < newRssi && newRssi < MAX_RSSI) { // screen out invalid values
             /* some implementations avoid negative values by adding 256
              * so we need to adjust for that here.
              */
@@ -1263,7 +1266,7 @@
             }
             mLastSignalLevel = newSignalLevel;
         } else {
-            mWifiInfo.setRssi(-200);
+            mWifiInfo.setRssi(MIN_RSSI);
         }
         int newLinkSpeed = WifiNative.getLinkSpeedCommand();
         if (newLinkSpeed != -1) {
@@ -1385,15 +1388,17 @@
         /* Disable interface */
         NetworkUtils.disableInterface(mInterfaceName);
 
-        /* send event to CM & network change broadcast */
-        setNetworkDetailedState(DetailedState.DISCONNECTED);
-        sendNetworkStateChangeBroadcast(mLastBssid);
-
         /* Reset data structures */
         mWifiInfo.setInetAddress(null);
         mWifiInfo.setBSSID(null);
         mWifiInfo.setSSID(null);
         mWifiInfo.setNetworkId(-1);
+        mWifiInfo.setRssi(MIN_RSSI);
+        mWifiInfo.setLinkSpeed(-1);
+
+        /* send event to CM & network change broadcast */
+        setNetworkDetailedState(DetailedState.DISCONNECTED);
+        sendNetworkStateChangeBroadcast(mLastBssid);
 
         /* Clear network properties */
         mLinkProperties.clear();
@@ -2362,7 +2367,10 @@
                     // 50023 supplicant_state_changed (custom|1|5)
                     EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, state.ordinal());
                     mWifiInfo.setSupplicantState(state);
-                    mWifiInfo.setNetworkId(stateChangeResult.networkId);
+                    // Network id is only valid when we start connecting
+                    if (SupplicantState.isConnecting(state)) {
+                        mWifiInfo.setNetworkId(stateChangeResult.networkId);
+                    }
                     if (state == SupplicantState.ASSOCIATING) {
                         /* BSSID is valid only in ASSOCIATING state */
                         mWifiInfo.setBSSID(stateChangeResult.BSSID);
@@ -2740,6 +2748,15 @@
             }
             return HANDLED;
         }
+        @Override
+        public void exit() {
+            /* If a scan result is pending in connected state, the supplicant
+             * is in SCAN_ONLY_MODE. Restore CONNECT_MODE on exit
+             */
+            if (mScanResultIsPending) {
+                WifiNative.setScanResultHandlingCommand(CONNECT_MODE);
+            }
+        }
     }
 
     class DisconnectingState extends HierarchicalState {