Fix DatagramSocket.disconnect()

Fix DatagramSocket.disconnect() in the case where an exception has
been thrown during connect().

commit 6764aa32a4b66a3c589f4a00615a1e36d87f308f introduced a bug
because it would leave connectState as ST_CONNECTED when
connect() failed. The correct state in this case appears to be
ST_CONNECTED_NO_IMPL instead (which is then dealt with correctly
by disconnect()).

This change rearranges the Android changes over upstream to make it
closer to upstream and try to make it clearer what state is guaranteed
after an exception is thrown.

Test: Ran CtsLibcoreTestCases
Bug: 31218085
(cherry picked from commit 979fbd7f58c33df7534cbc10a31cfc6aea85aac2)

Change-Id: I8b8e595a8c160b9dbc3450ae20da1be5fb91f47c
diff --git a/ojluni/src/main/java/java/net/DatagramSocket.java b/ojluni/src/main/java/java/net/DatagramSocket.java
index d089b89..13b54b0 100755
--- a/ojluni/src/main/java/java/net/DatagramSocket.java
+++ b/ojluni/src/main/java/java/net/DatagramSocket.java
@@ -142,39 +142,34 @@
         if (!isBound())
           bind(new InetSocketAddress(0));
 
-        // ----- BEGIN android -----
-        connectedAddress = address;
-        connectedPort = port;
-        // ----- END android -----
-
-        // old impls do not support connect/disconnect
-        if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
-             ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) {
-            connectState = ST_CONNECTED_NO_IMPL;
-        } else {
-          /* ----- BEGIN android -----
-          try {
-              getImpl().connect(address, port);
-
-              // socket is now connected by the impl
-              connectState = ST_CONNECTED;
-          } catch (SocketException se) {
-                // connection will be emulated by DatagramSocket
+        // Android-changed: This section now throws any SocketException generated by connect()
+        // to enable it to be recorded as the pendingConnectException. It has been enclosed in a
+        // try-finally to ensure connectedAddress and connectedPort are set when the exception
+        // is thrown.
+        try {
+            // old impls do not support connect/disconnect
+            // Android-changed: Added special handling for AbstractPlainDatagramSocketImpl in
+            // the condition below.
+            if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
+                    ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) {
                 connectState = ST_CONNECTED_NO_IMPL;
-          }*/
+            } else {
+                try {
+                    getImpl().connect(address, port);
 
-          // socket is now connected by the impl
-          connectState = ST_CONNECTED;
-
-          getImpl().connect(address, port);
-
-          // ----- END android -----
+                    // socket is now connected by the impl
+                    connectState = ST_CONNECTED;
+                } catch (SocketException se) {
+                    // connection will be emulated by DatagramSocket
+                    connectState = ST_CONNECTED_NO_IMPL;
+                    // Android-changed: Propagate the SocketException so connect() can store it.
+                    throw se;
+                }
+           }
+        } finally {
+            connectedAddress = address;
+            connectedPort = port;
         }
-
-        /* ----- BEGIN android -----
-        connectedAddress = address;
-        connectedPort = port;
-        ----- END android ----- */
     }