Merge "Update java.net.URL to OpenJDK 8u121-b13."
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
index 57c79d3..a24a67b 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.harmony.tests.java.net;
 
-import java.io.FileDescriptor;
 import java.io.IOException;
 import java.net.BindException;
 import java.net.DatagramPacket;
@@ -33,19 +32,11 @@
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
-import libcore.io.IoUtils;
-import libcore.io.Libcore;
 import libcore.junit.junit3.TestCaseWithRules;
 import libcore.junit.util.ResourceLeakageDetector;
 import org.junit.Rule;
 import org.junit.rules.TestRule;
 
-import android.system.ErrnoException;
-
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.IFF_RUNNING;
-import static android.system.OsConstants.SOCK_DGRAM;
-
 public class MulticastSocketTest extends TestCaseWithRules {
     @Rule
     public TestRule guardRule = ResourceLeakageDetector.getRule();
@@ -936,9 +927,6 @@
 
     private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
         return iface.isUp()
-                // On Oreo+ NetworkInterface.isUp() doesn't check the IFF_RUNNING flag so we do
-                // so here. http://b/71977275
-                && ((getOsFlags(iface) & IFF_RUNNING) != 0)
                 // Typically loopback interfaces do not support multicast, but we rule them out
                 // explicitly anyway.
                 && !iface.isLoopback()
@@ -948,20 +936,6 @@
                 && iface.getInetAddresses().hasMoreElements();
     }
 
-    private static int getOsFlags(NetworkInterface iface) throws IOException {
-        FileDescriptor fd = null;
-        try {
-            fd = Libcore.rawOs.socket(AF_INET, SOCK_DGRAM, 0);
-            return Libcore.rawOs.ioctlFlags(fd, iface.getName());
-        } catch (ErrnoException e) {
-            throw e.rethrowAsSocketException();
-        } catch (Exception ex) {
-            throw new SocketException(ex);
-        } finally {
-            IoUtils.closeQuietly(fd);
-        }
-    }
-
     private static MulticastSocket createReceivingSocket(int aPort) throws IOException {
         MulticastSocket ms = new MulticastSocket(aPort);
         ms.setSoTimeout(2000);
diff --git a/luni/src/main/java/libcore/util/TimeZoneFinder.java b/luni/src/main/java/libcore/util/TimeZoneFinder.java
index 860dcdf..3f2257e 100644
--- a/luni/src/main/java/libcore/util/TimeZoneFinder.java
+++ b/luni/src/main/java/libcore/util/TimeZoneFinder.java
@@ -161,6 +161,23 @@
     }
 
     /**
+     * Returns an immutable list of country ISO codes with time zones. The codes can be passed to
+     * {@link #lookupCountryTimeZones(String)} and similar methods. This method can return
+     * {@code null} in the event of an error while reading the underlying data files.
+     */
+    public List<String> getCountryIsoCodes() {
+        CountryIsoCodesExtractor extractor = new CountryIsoCodesExtractor();
+        try {
+            processXml(extractor);
+
+            return Collections.unmodifiableList(extractor.getCountryIsoCodes());
+        } catch (XmlPullParserException | IOException e) {
+            System.logW("Error reading country zones ", e);
+            return null;
+        }
+    }
+
+    /**
      * Returns a frozen ICU time zone that has / would have had the specified offset and DST value
      * at the specified moment in the specified country.
      *
@@ -569,6 +586,26 @@
     }
 
     /**
+     * Reads the time zone information and records the country ISO codes. The codes are then
+     * available via {@link #getCountryIsoCodes()}
+     */
+    private static class CountryIsoCodesExtractor implements CountryZonesProcessor {
+
+        private final List<String> countryIsoCodes = new ArrayList<>(200 /* reasonable default */);
+
+        @Override
+        public boolean process(String countryIso, String defaultTimeZoneId, boolean everUsesUtc,
+                List<String> timeZoneIds, String debugInfo) throws XmlPullParserException {
+            countryIsoCodes.add(countryIso);
+            return CONTINUE;
+        }
+
+        public List<String> getCountryIsoCodes() {
+            return countryIsoCodes;
+        }
+    }
+
+    /**
      * Extracts <em>validated</em> time zones information associated with a specific country code.
      * Processing is halted when the country code is matched and the validated result is also made
      * available via {@link #getValidatedCountryTimeZones()}.
diff --git a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
index d809eab..51c8b04 100644
--- a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
+++ b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
@@ -19,6 +19,7 @@
 import junit.framework.TestCase;
 
 import java.io.BufferedReader;
+import java.io.FileDescriptor;
 import java.io.InputStreamReader;
 import java.lang.reflect.Field;
 import java.net.Inet4Address;
@@ -34,7 +35,16 @@
 import java.util.List;
 import java.util.Set;
 import java.util.regex.Pattern;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
 
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.IFF_LOOPBACK;
+import static android.system.OsConstants.IFF_MULTICAST;
+import static android.system.OsConstants.IFF_POINTOPOINT;
+import static android.system.OsConstants.IFF_RUNNING;
+import static android.system.OsConstants.IFF_UP;
+import static android.system.OsConstants.SOCK_DGRAM;
 import static java.net.NetworkInterface.getNetworkInterfaces;
 
 public class NetworkInterfaceTest extends TestCase {
@@ -228,6 +238,34 @@
         }
     }
 
+    // b/71977275
+    public void testIsUp() throws Exception {
+        for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
+            int flags = getFlags(nif);
+            assertEquals(
+                    ((flags & IFF_UP) == IFF_UP) && ((flags & IFF_RUNNING) == IFF_RUNNING),
+                    nif.isUp());
+        }
+    }
+
+    public void testIsLoopback() throws Exception {
+        for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
+            assertEquals((getFlags(nif) & IFF_LOOPBACK) == IFF_LOOPBACK, nif.isLoopback());
+        }
+    }
+
+    public void testIsPointToPoint() throws Exception {
+        for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
+            assertEquals((getFlags(nif) & IFF_POINTOPOINT) == IFF_POINTOPOINT, nif.isPointToPoint());
+        }
+    }
+
+    public void testSupportsMulticast() throws Exception {
+        for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
+            assertEquals((getFlags(nif) & IFF_MULTICAST) == IFF_MULTICAST, nif.supportsMulticast());
+        }
+    }
+
     // Is ifName a name of a Ethernet device?
     private static Pattern ethernetNamePattern = Pattern.compile("^(eth|wlan)[0-9]+$");
     private static boolean isEthernet(String ifName) throws Exception {
@@ -239,4 +277,13 @@
             mcastSock.getNetworkInterface().getInterfaceAddresses();
         }
     }
+
+    private int getFlags(NetworkInterface nif) throws Exception {
+        FileDescriptor fd = Libcore.rawOs.socket(AF_INET, SOCK_DGRAM, 0);
+        try {
+            return Libcore.rawOs.ioctlFlags(fd, nif.getName());
+        } finally {
+            IoUtils.closeQuietly(fd);
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
index 38babc0..5013114 100644
--- a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
@@ -18,10 +18,6 @@
 
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
-
-import android.system.ErrnoException;
-
-import java.io.FileDescriptor;
 import java.io.IOException;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -41,13 +37,8 @@
 import java.util.Enumeration;
 
 import libcore.io.IoBridge;
-import libcore.io.IoUtils;
-import libcore.io.Libcore;
 
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.IFF_RUNNING;
 import static android.system.OsConstants.POLLIN;
-import static android.system.OsConstants.SOCK_DGRAM;
 
 /**
  * Tests associated with multicast behavior of DatagramChannel.
@@ -1232,32 +1223,12 @@
 
     private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
         return iface.isUp()
-                // On Oreo+ NetworkInterface.isUp() doesn't check the IFF_RUNNING flag so we do
-                // so here. http://b/71977275
-                && ((getOsFlags(iface) & IFF_RUNNING) != 0)
-                // Typically loopback interfaces do not support multicast, but we rule them out
-                // explicitly anyway.
-                && !iface.isLoopback()
-                // Point-to-point interfaces are known to cause problems. http://b/23279677
-                && !iface.isPointToPoint()
-                && iface.supportsMulticast()
+                // Typically loopback interfaces do not support multicast, but they are ruled out
+                // explicitly here anyway.
+                && !iface.isLoopback() && iface.supportsMulticast()
                 && iface.getInetAddresses().hasMoreElements();
     }
 
-    private static int getOsFlags(NetworkInterface iface) throws IOException {
-        FileDescriptor fd = null;
-        try {
-            fd = Libcore.rawOs.socket(AF_INET, SOCK_DGRAM, 0);
-            return Libcore.rawOs.ioctlFlags(fd, iface.getName());
-        } catch (ErrnoException e) {
-            throw e.rethrowAsSocketException();
-        } catch (Exception ex) {
-            throw new SocketException(ex);
-        } finally {
-            IoUtils.closeQuietly(fd);
-        }
-    }
-
     private static void createChannelAndSendMulticastMessage(
             InetAddress group, int port, String msg, NetworkInterface sendingInterface)
             throws IOException {
diff --git a/luni/src/test/java/libcore/libcore/util/TimeZoneFinderTest.java b/luni/src/test/java/libcore/libcore/util/TimeZoneFinderTest.java
index ce653c52..9e807e7 100644
--- a/luni/src/test/java/libcore/libcore/util/TimeZoneFinderTest.java
+++ b/luni/src/test/java/libcore/libcore/util/TimeZoneFinderTest.java
@@ -832,7 +832,36 @@
         assertEquals(expectedIanaVersion, finder.getIanaVersion());
     }
 
-    private void assertImmutableTimeZone(TimeZone timeZone) {
+    @Test
+    public void getCountryIsoCodes() throws Exception {
+        TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n"
+                + "  <countryzones>\n"
+                + "    <country code=\"gb\" default=\"Europe/London\" everutc=\"y\">\n"
+                + "      <id>Europe/London</id>\n"
+                + "    </country>\n"
+                + "    <country code=\"fr\" default=\"Europe/Paris\" everutc=\"y\">\n"
+                + "      <id>Europe/Paris</id>\n"
+                + "    </country>\n"
+                + "  </countryzones>\n"
+                + "</timezones>\n");
+
+        List<String> isoList = finder.getCountryIsoCodes();
+        assertEquals(list("gb", "fr"), isoList);
+        assertImmutableList(isoList);
+    }
+
+    @Test
+    public void getCountryIsoCodes_empty() throws Exception {
+        TimeZoneFinder finder = validate("<timezones ianaversion=\"2017b\">\n"
+                + "  <countryzones>\n"
+                + "  </countryzones>\n"
+                + "</timezones>\n");
+        List<String> isoList = finder.getCountryIsoCodes();
+        assertEquals(list(), isoList);
+        assertImmutableList(isoList);
+    }
+
+    private static void assertImmutableTimeZone(TimeZone timeZone) {
         try {
             timeZone.setRawOffset(1000);
             fail();
diff --git a/ojluni/src/main/java/java/net/NetworkInterface.java b/ojluni/src/main/java/java/net/NetworkInterface.java
index e465d0b..673a1d2 100644
--- a/ojluni/src/main/java/java/net/NetworkInterface.java
+++ b/ojluni/src/main/java/java/net/NetworkInterface.java
@@ -477,7 +477,8 @@
 
     public boolean isUp() throws SocketException {
         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
-        return (getFlags() & IFF_UP) != 0;
+        final int mask = IFF_UP | IFF_RUNNING;
+        return (getFlags() & mask) == mask;
     }
 
     /**