Merge changes I1d25e5c4,I367f5377 into main am: ee58f011ed

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/3554881

Change-Id: I871477ea7e232b93e00ac9adf8f813ec01f4660f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index 1c453cb..7a192ce 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -69,7 +69,6 @@
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
@@ -104,6 +103,22 @@
     // TODO: consider using SharedLog consistently across ethernet service.
     private static final SharedLog sLog = new SharedLog(TAG);
 
+    @VisibleForTesting
+    public static final NetworkCapabilities DEFAULT_CAPABILITIES = new NetworkCapabilities.Builder()
+                        .addTransportType(TRANSPORT_ETHERNET)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+                        // TODO: do not hardcode link bandwidth.
+                        .setLinkUpstreamBandwidthKbps(100 * 1000 /* 100 Mbps */)
+                        .setLinkDownstreamBandwidthKbps(100 * 1000 /* 100 Mbps */)
+                        .build();
+
+
     /**
      * Interface names we track. This is a product-dependent regular expression.
      * Use isValidEthernetInterface to check if a interface name is a valid ethernet interface (this
@@ -648,7 +663,7 @@
             nc = mNetworkCapabilities.get(hwAddress);
             if (nc == null) {
                 final boolean isTestIface = iface.matches(TEST_IFACE_REGEXP);
-                nc = createDefaultNetworkCapabilities(isTestIface, TRANSPORT_ETHERNET);
+                nc = createDefaultNetworkCapabilities(isTestIface);
             }
         }
 
@@ -762,24 +777,9 @@
      * <interface name|mac address>;[Network Capabilities];[IP config];[Override Transport]}
      */
     private void parseEthernetConfig(String configString) {
-        final EthernetConfigParser config = new EthernetConfigParser(configString);
-        NetworkCapabilities nc;
-        // Starting with Android B (API level 36), we provide default NetworkCapabilities
-        // for Ethernet interfaces when no explicit capabilities are specified in the
-        // configuration string. This change is made to ensure consistent and expected
-        // network behavior for Ethernet devices.
-        //
-        // It's possible that OEMs or device manufacturers may have relied on the previous
-        // behavior (where interfaces without specified capabilities would have minimal
-        // capabilities) to prevent certain Ethernet interfaces from becoming
-        // the default network. To avoid breaking existing device configurations, this
-        // change is gated by the SDK level.
-        if (mDeps.isAtLeastB() && config.mCaps.isEmpty()) {
-            nc = createDefaultNetworkCapabilities(false /* isTestIface */, config.mTransport);
-        } else {
-            nc = createNetworkCapabilities(config.mCaps, config.mTransport).build();
-        }
-        mNetworkCapabilities.put(config.mIface, nc);
+        final EthernetConfigParser config =
+                new EthernetConfigParser(configString, mDeps.isAtLeastB());
+        mNetworkCapabilities.put(config.mIface, config.mCaps);
 
         if (null != config.mIpConfig) {
             IpConfiguration ipConfig = parseStaticIpConfiguration(config.mIpConfig);
@@ -787,66 +787,19 @@
         }
     }
 
-    private static NetworkCapabilities createDefaultNetworkCapabilities(
-            boolean isTestIface, int transportType) {
-        NetworkCapabilities.Builder builder =
-                createNetworkCapabilities(Collections.emptyList(), transportType)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
-
+    private static NetworkCapabilities createDefaultNetworkCapabilities(boolean isTestIface) {
+        final NetworkCapabilities.Builder builder =
+                new NetworkCapabilities.Builder(DEFAULT_CAPABILITIES);
         if (isTestIface) {
             builder.addTransportType(NetworkCapabilities.TRANSPORT_TEST);
-        } else {
-            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+            // TODO: do not remove INTERNET capability for test networks.
+            builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
         }
 
         return builder.build();
     }
 
     /**
-     * Parses a static list of network capabilities
-     *
-     * @param capabilities      A List of NetworkCapabilities.
-     * @param overrideTransport A string representing a single integer encoded override transport
-     *                          type. Must be one of the NetworkCapability.TRANSPORT_*
-     *                          values. TRANSPORT_VPN is not supported. Errors with input
-     *                          will cause the override to be ignored.
-     */
-    @VisibleForTesting
-    static NetworkCapabilities.Builder createNetworkCapabilities(List<Integer> capabilities,
-            int transportType) {
-
-        final NetworkCapabilities.Builder builder =
-                capabilities.isEmpty()
-                        ? new NetworkCapabilities.Builder()
-                        : NetworkCapabilities.Builder.withoutDefaultCapabilities();
-
-        // Determine the transport type. If someone has tried to define an override transport then
-        // attempt to add it. Since we can only have one override, all errors with it will
-        // gracefully default back to TRANSPORT_ETHERNET and warn the user. VPN is not allowed as an
-        // override type. Wifi Aware and LoWPAN are currently unsupported as well.
-        builder.addTransportType(transportType);
-
-        builder.setLinkUpstreamBandwidthKbps(100 * 1000);
-        builder.setLinkDownstreamBandwidthKbps(100 * 1000);
-
-        for (int capability : capabilities) {
-            builder.addCapability(capability);
-        }
-        // Ethernet networks have no way to update the following capabilities, so they always
-        // have them.
-        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
-        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
-        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
-
-        return builder;
-    }
-
-    /**
      * Parses static IP configuration.
      *
      * @param staticIpConfig represents static IP configuration in the following format: {@code
@@ -1017,30 +970,44 @@
     @VisibleForTesting
     static class EthernetConfigParser {
         final String mIface;
-        final List<Integer> mCaps;
+        final NetworkCapabilities mCaps;
         final String mIpConfig;
-        final int mTransport;
 
-        private static List<Integer> parseCapabilities(@Nullable String capabilitiesString) {
-            if (TextUtils.isEmpty(capabilitiesString)) {
-                return Collections.emptyList();
+        private static NetworkCapabilities parseCapabilities(@Nullable String capabilitiesString,
+                boolean isAtLeastB) {
+            final NetworkCapabilities.Builder builder =
+                    NetworkCapabilities.Builder.withoutDefaultCapabilities();
+            builder.setLinkUpstreamBandwidthKbps(100 * 1000 /* 100 Mbps */);
+            builder.setLinkDownstreamBandwidthKbps(100 * 1000 /* 100 Mbps */);
+            // Ethernet networks have no way to update the following capabilities, so they always
+            // have them.
+            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
+            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
+            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
+
+            if (capabilitiesString == null) {
+                return builder.build();
             }
 
-            final ArrayList<Integer> capabilities = new ArrayList<>();
+            if (isAtLeastB && capabilitiesString.equals("*")) {
+                // On Android B+, a "*" string defaults to the same set of default
+                // capabilities assigned to unconfigured interfaces.
+                return new NetworkCapabilities(DEFAULT_CAPABILITIES);
+            }
+
             for (String strNetworkCapability : capabilitiesString.split(",")) {
                 if (TextUtils.isEmpty(strNetworkCapability)) {
                     continue;
                 }
                 final Integer capability;
                 try {
-                    capability = Integer.valueOf(strNetworkCapability);
+                    builder.addCapability(Integer.valueOf(strNetworkCapability));
                 } catch (NumberFormatException e) {
                     Log.e(TAG, "Failed to parse capability: " + strNetworkCapability, e);
                     continue;
                 }
-                capabilities.add(capability);
             }
-            return Collections.unmodifiableList(capabilities);
+            return builder.build();
         }
 
         private static int parseTransportType(@Nullable String transportString) {
@@ -1071,13 +1038,18 @@
             }
         }
 
-        EthernetConfigParser(String configString) {
+        EthernetConfigParser(String configString, boolean isAtLeastB) {
             Objects.requireNonNull(configString, "EthernetConfigParser requires non-null config");
             final String[] tokens = configString.split(";", /* limit of tokens */ 4);
             mIface = tokens[0];
-            mCaps = parseCapabilities(tokens.length > 1 ? tokens[1] : null);
+
+            final NetworkCapabilities nc =
+                    parseCapabilities(tokens.length > 1 ? tokens[1] : null, isAtLeastB);
+            final int transportType = parseTransportType(tokens.length > 3 ? tokens[3] : null);
+            nc.addTransportType(transportType);
+            mCaps = nc;
+
             mIpConfig = tokens.length > 2 && !TextUtils.isEmpty(tokens[2]) ? tokens[2] : null;
-            mTransport = parseTransportType(tokens.length > 3 ? tokens[3] : null);
         }
     }
 }
diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml
index 1b0f29d..514563b 100644
--- a/service/ServiceConnectivityResources/res/values/config.xml
+++ b/service/ServiceConnectivityResources/res/values/config.xml
@@ -193,6 +193,8 @@
                    The NOT_ROAMING, NOT_CONGESTED and NOT_SUSPENDED capabilities are always
                    added automatically because this configuration provides no way to update
                    them dynamically.
+                   On Android B+, a "*" string configures the same default capabilities as is
+                   used for interfaces without any explicit configuration.
                [IP config] Optional. If empty or not specified - DHCP will be used, otherwise
                    use the following format to specify static IP configuration:
                        ip=<ip-address/mask> gateway=<ip-address> dns=<comma-sep-ip-addresses>
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
index 03fb505..c1291b0 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
@@ -180,163 +180,77 @@
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
     }
 
-    /**
-     * Test: Attempt to create a capabilities with various valid sets of capabilities/transports
-     */
+
     @Test
-    public void createNetworkCapabilities() {
-        // Particularly common expected results
-        NetworkCapabilities defaultCapabilities =
-                makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
-                        .setLinkUpstreamBandwidthKbps(100000)
-                        .setLinkDownstreamBandwidthKbps(100000)
-                        .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
-                        .build();
+    public void testNetworkCapabilityParsing() {
+        final NetworkCapabilities baseNc = NetworkCapabilities.Builder.withoutDefaultCapabilities()
+                .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
+                .setLinkUpstreamBandwidthKbps(100 * 1000 /* 100 Mbps */)
+                .setLinkDownstreamBandwidthKbps(100 * 1000 /* 100 Mbps */)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+                .build();
 
-        NetworkCapabilities ethernetClearedWithCommonCaps =
-                makeEthernetCapabilitiesBuilder(true /* clearDefaults */)
-                        .setLinkUpstreamBandwidthKbps(100000)
-                        .setLinkDownstreamBandwidthKbps(100000)
-                        .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
-                        .addCapability(12)
-                        .addCapability(13)
-                        .addCapability(14)
-                        .addCapability(15)
-                        .build();
+        // Empty capabilities always default to the baseNc above.
+        EthernetConfigParser parser = new EthernetConfigParser("eth0;", false /*isAtLeastB*/);
+        assertThat(parser.mCaps).isEqualTo(baseNc);
+        parser = new EthernetConfigParser("eth0;", true /*isAtLeastB*/);
+        assertThat(parser.mCaps).isEqualTo(baseNc);
 
-        // Empty capabilities and transports should return the default capabilities set
-        // with TRANSPORT_ETHERNET
-        assertParsedNetworkCapabilities(defaultCapabilities, "", "");
+        // On Android B+, "*" defaults to using DEFAULT_CAPABILITIES.
+        parser = new EthernetConfigParser("eth0;*;;;;;;", true /*isAtLeastB*/);
+        assertThat(parser.mCaps).isEqualTo(EthernetTracker.DEFAULT_CAPABILITIES);
 
-        // Adding a list of capabilities will leave exactly those capabilities with a default
-        // TRANSPORT_ETHERNET since no overrides are specified
-        assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, "12,13,14,15", "");
+        // But not so before B.
+        parser = new EthernetConfigParser("eth0;*", false /*isAtLeastB*/);
+        assertThat(parser.mCaps).isEqualTo(baseNc);
 
-        // Adding any invalid capabilities to the list will cause them to be ignored
-        assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, "12,13,14,15,65,73", "");
-        assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, "12,13,14,15,abcdefg", "");
+        parser = new EthernetConfigParser("eth0;12,13,14,15;", false /*isAtLeastB*/);
+        assertThat(parser.mCaps.getCapabilities()).asList().containsAtLeast(12, 13, 14, 15);
 
-        // Adding a valid override transport will remove the default TRANSPORT_ETHERNET transport
-        // and apply only the override to the capabilities object
-        assertParsedNetworkCapabilities(
-                makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
-                        .setLinkUpstreamBandwidthKbps(100000)
-                        .setLinkDownstreamBandwidthKbps(100000)
-                        .addTransportType(0)
-                        .build(),
-                "",
-                "0");
-        assertParsedNetworkCapabilities(
-                makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
-                        .setLinkUpstreamBandwidthKbps(100000)
-                        .setLinkDownstreamBandwidthKbps(100000)
-                        .addTransportType(1)
-                        .build(),
-                "",
-                "1");
-        assertParsedNetworkCapabilities(
-                makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
-                        .setLinkUpstreamBandwidthKbps(100000)
-                        .setLinkDownstreamBandwidthKbps(100000)
-                        .addTransportType(2)
-                        .build(),
-                "",
-                "2");
-        assertParsedNetworkCapabilities(
-                makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
-                        .setLinkUpstreamBandwidthKbps(100000)
-                        .setLinkDownstreamBandwidthKbps(100000)
-                        .addTransportType(3)
-                        .build(),
-                "",
-                "3");
+        parser = new EthernetConfigParser("eth0;12,13,500,abc", false /*isAtLeastB*/);
+        // 18, 20, 21 are added by EthernetConfigParser.
+        assertThat(parser.mCaps.getCapabilities()).asList().containsExactly(12, 13, 18, 20, 21);
 
-        // "4" is TRANSPORT_VPN, which is unsupported. Should default back to TRANSPORT_ETHERNET
-        assertParsedNetworkCapabilities(defaultCapabilities, "", "4");
+        parser = new EthernetConfigParser("eth0;1,2,3;;0", false /*isAtLeastB*/);
+        assertThat(parser.mCaps.getCapabilities()).asList().containsAtLeast(1, 2, 3);
+        assertThat(parser.mCaps.hasSingleTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
 
-        // "5" is TRANSPORT_WIFI_AWARE, which is currently supported due to no legacy TYPE_NONE
-        // conversion. When that becomes available, this test must be updated
-        assertParsedNetworkCapabilities(defaultCapabilities, "", "5");
+        // TRANSPORT_VPN (4) is not allowed.
+        parser = new EthernetConfigParser("eth0;;;4", false /*isAtLeastB*/);
+        assertThat(parser.mCaps.hasSingleTransport(NetworkCapabilities.TRANSPORT_ETHERNET)).isTrue();
 
-        // "6" is TRANSPORT_LOWPAN, which is currently supported due to no legacy TYPE_NONE
-        // conversion. When that becomes available, this test must be updated
-        assertParsedNetworkCapabilities(defaultCapabilities, "", "6");
-
-        // Adding an invalid override transport will leave the transport as TRANSPORT_ETHERNET
-        assertParsedNetworkCapabilities(defaultCapabilities, "", "100");
-        assertParsedNetworkCapabilities(defaultCapabilities, "", "abcdefg");
-
-        // Ensure the adding of both capabilities and transports work
-        assertParsedNetworkCapabilities(
-                makeEthernetCapabilitiesBuilder(true /* clearDefaults */)
-                        .setLinkUpstreamBandwidthKbps(100000)
-                        .setLinkDownstreamBandwidthKbps(100000)
-                        .addCapability(12)
-                        .addCapability(13)
-                        .addCapability(14)
-                        .addCapability(15)
-                        .addTransportType(3)
-                        .build(),
-                "12,13,14,15",
-                "3");
-
-        // Ensure order does not matter for capability list
-        assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, "13,12,15,14", "");
-    }
-
-    private void assertParsedNetworkCapabilities(
-            NetworkCapabilities expectedNetworkCapabilities,
-            String configCapabilities,
-            String configTransports) {
-        final String ipConfig = "";
-        final String configString =
-                String.join(";", TEST_IFACE, configCapabilities, ipConfig, configTransports);
-        final EthernetConfigParser config = new EthernetConfigParser(configString);
-        assertEquals(
-                expectedNetworkCapabilities,
-                EthernetTracker.createNetworkCapabilities(config.mCaps, config.mTransport).build());
+        // invalid capability and transport type
+        parser = new EthernetConfigParser("eth0;-1,a,1000,,;;-1", false /*isAtLeastB*/);
+        assertThat(parser.mCaps).isEqualTo(baseNc);
     }
 
     @Test
-    public void testCreateEthernetConfigParserReturnsCorrectValue() {
-        final String capabilities = "2,4,6,8";
-        final String ipConfig = "3";
-        final String transport = "1";
-        final String configString = String.join(";", TEST_IFACE, capabilities, ipConfig, transport);
+    public void testInterfaceNameParsing() {
+        EthernetConfigParser parser = new EthernetConfigParser("eth12", false /*isAtLeastB*/);
+        assertThat(parser.mIface).isEqualTo("eth12");
 
-        final EthernetConfigParser config = new EthernetConfigParser(configString);
+        parser = new EthernetConfigParser("", true /*isAtLeastB*/);
+        assertThat(parser.mIface).isEqualTo("");
 
-        assertEquals(TEST_IFACE, config.mIface);
-        assertThat(config.mCaps).containsExactly(2, 4, 6, 8);
-        assertEquals(ipConfig, config.mIpConfig);
-        assertEquals(NetworkCapabilities.TRANSPORT_WIFI, config.mTransport);
+        parser = new EthernetConfigParser("eth0;12;", true /*isAtLeastB*/);
+        assertThat(parser.mIface).isEqualTo("eth0");
     }
 
     @Test
-    public void testCreateEthernetConfigParser_withInvalidTransport() {
-        final String capabilities = "2";
-        final String ipConfig = "3";
-        final String transport = "100"; // Invalid transport type
-        final String configString = String.join(";", TEST_IFACE, capabilities, ipConfig, transport);
-
-        final EthernetConfigParser config = new EthernetConfigParser(configString);
-        assertEquals(NetworkCapabilities.TRANSPORT_ETHERNET, config.mTransport);
-    }
-
-    @Test
-    public void testCreateEthernetConfigParser_withDisallowedTransport() {
-        final String capabilities = "2";
-        final String ipConfig = "3";
-        final String transport = "4"; // TRANSPORT_VPN is not allowed
-        final String configString = String.join(";", TEST_IFACE, capabilities, ipConfig, transport);
-
-        final EthernetConfigParser config = new EthernetConfigParser(configString);
-        assertEquals(NetworkCapabilities.TRANSPORT_ETHERNET, config.mTransport);
+    public void testIpConfigParsing() {
+        // Note that EthernetConfigParser doesn't actually parse the IpConfig (yet).
+        final EthernetConfigParser parser = new EthernetConfigParser(
+                "eth0;1,2,3;ip=192.168.0.10/24 gateway=192.168.0.1 dns=4.4.4.4,8.8.8.8;1",
+                false /*isAtLeastB*/);
+        assertThat(parser.mIpConfig)
+                .isEqualTo("ip=192.168.0.10/24 gateway=192.168.0.1 dns=4.4.4.4,8.8.8.8");
     }
 
     @Test
     public void testCreateEthernetConfigParserThrowsNpeWithNullInput() {
-        assertThrows(NullPointerException.class, () -> new EthernetConfigParser(null));
+        assertThrows(NullPointerException.class, () -> new EthernetConfigParser(null, false));
     }
 
     @Test