Merge changes I514b5b3a,Id67082c5 into rvc-dev

* changes:
  ClientModeImpl: Ignore connect when connecting to network
  WifiDiagnostics: Add a timeout for logcat calls
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index ac1c8d0..5b616dd 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -368,7 +368,7 @@
     private String mTargetBssid = SUPPLICANT_BSSID_ANY;
     // This one is used to track the current target network ID. This is used for error
     // handling during connection setup since many error message from supplicant does not report
-    // SSID Once connected, it will be set to invalid
+    // SSID. Once connected, it will be set to invalid
     private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
     private long mLastDriverRoamAttempt = 0;
     private WifiConfiguration mTargetWifiConfiguration = null;
@@ -1211,8 +1211,8 @@
     private void connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect) {
         logd("connectToUserSelectNetwork netId " + netId + ", uid " + uid
                 + ", forceReconnect = " + forceReconnect);
-        if (!forceReconnect && mWifiInfo.getNetworkId() == netId) {
-            // We're already connected to the user specified network, don't trigger a
+        if (!forceReconnect && (mLastNetworkId == netId || mTargetNetworkId == netId)) {
+            // We're already connecting/connected to the user specified network, don't trigger a
             // reconnection unless it was forced.
             logi("connectToUserSelectNetwork already connecting/connected=" + netId);
         } else {
diff --git a/service/java/com/android/server/wifi/WifiDiagnostics.java b/service/java/com/android/server/wifi/WifiDiagnostics.java
index 4ac9820..2ba90c9 100644
--- a/service/java/com/android/server/wifi/WifiDiagnostics.java
+++ b/service/java/com/android/server/wifi/WifiDiagnostics.java
@@ -44,6 +44,7 @@
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.zip.Deflater;
 
@@ -107,6 +108,9 @@
     /** Minimum dump period with same error code */
     public static final long MIN_DUMP_TIME_WINDOW_MILLIS = 10 * 60 * 1000; // 10 mins
 
+    // Timeout for logcat
+    private static final int LOGCAT_TIMEOUT_MILLIS = 500;
+
     private long mLastBugReportTime;
 
     @VisibleForTesting public static final String FIRMWARE_DUMP_SECTION_HEADER =
@@ -720,7 +724,7 @@
             while ((line = reader.readLine()) != null) {
                 lines.add(line);
             }
-            process.waitFor();
+            process.waitFor(LOGCAT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
         } catch (InterruptedException|IOException e) {
             mLog.dump("Exception while capturing logcat: %").c(e.toString()).flush();
         }
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index bb9db6d..bc29d34 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -1538,6 +1538,60 @@
     }
 
     /**
+     * If caller tries to connect to a network that is already connecting, the connection request
+     * should succeed.
+     *
+     * Test: Create and trigger connect to a network, then try to reconnect to the same network.
+     * Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED and did not trigger a
+     * new connection.
+     */
+    @Test
+    public void reconnectToConnectingNetwork() throws Exception {
+        triggerConnect();
+
+        // try to reconnect to the same network (before connection is established).
+        IActionListener connectActionListener = mock(IActionListener.class);
+        mCmi.connect(null, FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0,
+                Binder.getCallingUid());
+        mLooper.dispatchAll();
+        verify(connectActionListener).onSuccess();
+
+        // Verify that we didn't trigger a second connection.
+        verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
+    }
+
+    /**
+     * If caller tries to connect to a network that is already connecting, the connection request
+     * should succeed.
+     *
+     * Test: Create and trigger connect to a network, then try to reconnect to the same network.
+     * Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED and did trigger a new
+     * connection.
+     */
+    @Test
+    public void reconnectToConnectingNetworkWithCredentialChange() throws Exception {
+        triggerConnect();
+
+        // try to reconnect to the same network with a credential changed (before connection is
+        // established).
+        WifiConfiguration config = new WifiConfiguration();
+        config.networkId = FRAMEWORK_NETWORK_ID;
+        NetworkUpdateResult networkUpdateResult =
+                new NetworkUpdateResult(false /* ip */, false /* proxy */, true /* credential */);
+        networkUpdateResult.setNetworkId(FRAMEWORK_NETWORK_ID);
+        when(mWifiConfigManager.addOrUpdateNetwork(eq(config), anyInt()))
+                .thenReturn(networkUpdateResult);
+        IActionListener connectActionListener = mock(IActionListener.class);
+        mCmi.connect(config, WifiConfiguration.INVALID_NETWORK_ID, mock(Binder.class),
+                connectActionListener, 0, Binder.getCallingUid());
+        mLooper.dispatchAll();
+        verify(connectActionListener).onSuccess();
+
+        // Verify that we triggered a second connection.
+        verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
+    }
+
+    /**
      * If caller tries to connect to a new network while still provisioning the current one,
      * the connection attempt should succeed.
      */