Add hasFlag method in NetdUtils.

Since ethernet-service related files are going to be moved into
Connectivity module. To deal with InterfaceConfiguration dependency
in EthernetTracker, use InterfaceConfigurationParcel instead, which
returns from NetdUtils API directly. Adding a new method hasFlag in
NetdUtils to replace the original InterfaceConfiguration.hasFlag,
that's invisible to the Connectivity module.

Bug: 210586283
Test: atest NetdStaticLibTests --iterations
Change-Id: I16fcbfb8f36c8632a8267ce55cdcbd78ea6edd1a
diff --git a/staticlibs/client-libs/netd/com/android/net/module/util/NetdUtils.java b/staticlibs/client-libs/netd/com/android/net/module/util/NetdUtils.java
index e78e336..3818d1f 100644
--- a/staticlibs/client-libs/netd/com/android/net/module/util/NetdUtils.java
+++ b/staticlibs/client-libs/netd/com/android/net/module/util/NetdUtils.java
@@ -37,7 +37,10 @@
 import androidx.annotation.VisibleForTesting;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Collection of utilities for netd.
@@ -69,6 +72,19 @@
         }
     }
 
+    /**
+     * Check whether the InterfaceConfigurationParcel contains the target flag or not.
+     *
+     * @param config The InterfaceConfigurationParcel instance.
+     * @param flag Target flag string to be checked.
+     */
+    public static boolean hasFlag(@NonNull final InterfaceConfigurationParcel config,
+            @NonNull final String flag) {
+        validateFlag(flag);
+        final Set<String> flagList = new HashSet<String>(Arrays.asList(config.flags));
+        return flagList.contains(flag);
+    }
+
     @VisibleForTesting
     protected static String[] removeAndAddFlags(@NonNull String[] flags, @NonNull String remove,
             @NonNull String add) {
diff --git a/staticlibs/client-libs/tests/unit/src/com/android/net/module/util/NetdUtilsTest.java b/staticlibs/client-libs/tests/unit/src/com/android/net/module/util/NetdUtilsTest.java
index dedda7e..5069672 100644
--- a/staticlibs/client-libs/tests/unit/src/com/android/net/module/util/NetdUtilsTest.java
+++ b/staticlibs/client-libs/tests/unit/src/com/android/net/module/util/NetdUtilsTest.java
@@ -22,6 +22,8 @@
 import static com.android.testutils.MiscAsserts.assertThrows;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -48,6 +50,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -218,4 +221,56 @@
         // Test throwing RemoteException after 3 tries.
         runTetherInterfaceWithRemoteException(3);
     }
+
+    @Test
+    public void testNetdUtilsHasFlag() throws Exception {
+        final String[] flags = new String[] {"up", "broadcast", "running", "multicast"};
+        setupFlagsForInterfaceConfiguration(flags);
+
+        // Set interface up.
+        NetdUtils.setInterfaceUp(mNetd, IFACE);
+        final ArgumentCaptor<InterfaceConfigurationParcel> arg =
+                ArgumentCaptor.forClass(InterfaceConfigurationParcel.class);
+        verify(mNetd, times(1)).interfaceSetCfg(arg.capture());
+
+        final InterfaceConfigurationParcel p = arg.getValue();
+        assertTrue(NetdUtils.hasFlag(p, "up"));
+        assertTrue(NetdUtils.hasFlag(p, "running"));
+        assertTrue(NetdUtils.hasFlag(p, "broadcast"));
+        assertTrue(NetdUtils.hasFlag(p, "multicast"));
+        assertFalse(NetdUtils.hasFlag(p, "down"));
+    }
+
+    @Test
+    public void testNetdUtilsHasFlag_flagContainsSpace() throws Exception {
+        final String[] flags = new String[] {"up", "broadcast", "running", "multicast"};
+        setupFlagsForInterfaceConfiguration(flags);
+
+        // Set interface up.
+        NetdUtils.setInterfaceUp(mNetd, IFACE);
+        final ArgumentCaptor<InterfaceConfigurationParcel> arg =
+                ArgumentCaptor.forClass(InterfaceConfigurationParcel.class);
+        verify(mNetd, times(1)).interfaceSetCfg(arg.capture());
+
+        final InterfaceConfigurationParcel p = arg.getValue();
+        assertThrows(IllegalArgumentException.class, () -> NetdUtils.hasFlag(p, "up "));
+    }
+
+    @Test
+    public void testNetdUtilsHasFlag_UppercaseString() throws Exception {
+        final String[] flags = new String[] {"up", "broadcast", "running", "multicast"};
+        setupFlagsForInterfaceConfiguration(flags);
+
+        // Set interface up.
+        NetdUtils.setInterfaceUp(mNetd, IFACE);
+        final ArgumentCaptor<InterfaceConfigurationParcel> arg =
+                ArgumentCaptor.forClass(InterfaceConfigurationParcel.class);
+        verify(mNetd, times(1)).interfaceSetCfg(arg.capture());
+
+        final InterfaceConfigurationParcel p = arg.getValue();
+        assertFalse(NetdUtils.hasFlag(p, "UP"));
+        assertFalse(NetdUtils.hasFlag(p, "BROADCAST"));
+        assertFalse(NetdUtils.hasFlag(p, "RUNNING"));
+        assertFalse(NetdUtils.hasFlag(p, "MULTICAST"));
+    }
 }