Merge "Make strict mode not triggered while connecting UDP socket"
diff --git a/luni/src/main/java/libcore/io/BlockGuardOs.java b/luni/src/main/java/libcore/io/BlockGuardOs.java
index d56e182..bd95a93 100644
--- a/luni/src/main/java/libcore/io/BlockGuardOs.java
+++ b/luni/src/main/java/libcore/io/BlockGuardOs.java
@@ -121,14 +121,29 @@
         return linger.isOn() && linger.l_linger > 0;
     }
 
-    @Override public void connect(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException {
-        BlockGuard.getThreadPolicy().onNetwork();
+    private static boolean isUdpSocket(FileDescriptor fd) throws ErrnoException {
+        return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) == IPPROTO_UDP;
+    }
+
+    @Override public void connect(FileDescriptor fd, InetAddress address, int port)
+            throws ErrnoException, SocketException {
+        boolean skipGuard = false;
+        try {
+            skipGuard = isUdpSocket(fd);
+        } catch (ErrnoException ignored) {
+        }
+        if (!skipGuard) BlockGuard.getThreadPolicy().onNetwork();
         super.connect(fd, address, port);
     }
 
     @Override public void connect(FileDescriptor fd, SocketAddress address) throws ErrnoException,
             SocketException {
-        BlockGuard.getThreadPolicy().onNetwork();
+        boolean skipGuard = false;
+        try {
+            skipGuard = isUdpSocket(fd);
+        } catch (ErrnoException ignored) {
+        }
+        if (!skipGuard) BlockGuard.getThreadPolicy().onNetwork();
         super.connect(fd, address);
     }
 
diff --git a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
index 471906f..0e2c6b5 100644
--- a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
+++ b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
@@ -16,6 +16,12 @@
 
 package libcore.libcore.io;
 
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.IPPROTO_TCP;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_STREAM;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -28,6 +34,8 @@
 import android.system.OsConstants;
 import android.system.StructAddrinfo;
 
+import java.io.FileDescriptor;
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.net.InetAddress;
@@ -39,6 +47,8 @@
 import java.util.regex.Pattern;
 
 import libcore.io.BlockGuardOs;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
 import libcore.io.Os;
 
 import dalvik.system.BlockGuard;
@@ -48,6 +58,8 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -130,6 +142,31 @@
         }
     }
 
+    @Test
+    public void test_connect_networkPolicy() throws ErrnoException, IOException {
+        BlockGuardOs blockGuardOs = new BlockGuardOs(mockOsDelegate);
+
+        // Test connect with a UDP socket that will not trigger a network policy check.
+        FileDescriptor udpSocket = Libcore.os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+        try {
+            blockGuardOs.connect(udpSocket, InetAddress.getLoopbackAddress(), 0);
+            verify(mockThreadPolicy, never()).onNetwork();
+            verify(mockOsDelegate, times(1)).connect(eq(udpSocket), any(), anyInt());
+        } finally {
+            IoUtils.closeQuietly(udpSocket);
+        }
+
+        // Test connect with a TCP socket that will trigger a network policy check.
+        FileDescriptor tcpSocket = Libcore.os.socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+        try {
+            blockGuardOs.connect(tcpSocket, InetAddress.getLoopbackAddress(), 0);
+            verify(mockThreadPolicy, times(1)).onNetwork();
+            verify(mockOsDelegate, times(1)).connect(eq(tcpSocket), any(), anyInt());
+        } finally {
+            IoUtils.closeQuietly(tcpSocket);
+        }
+    }
+
     /**
      * Checks that BlockGuardOs is updated when the Os interface changes. BlockGuardOs extends
      * ForwardingOs so doing so isn't an obvious step and it can be missed. When adding methods to