diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 1c453cb4e8..7a192cefff 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.InetAddress; 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 @@ public class EthernetTracker { // 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 @@ public class EthernetTracker { 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 @@ public class EthernetTracker { * ;[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,65 +787,18 @@ public class EthernetTracker { } } - 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 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. * @@ -1017,30 +970,44 @@ public class EthernetTracker { @VisibleForTesting static class EthernetConfigParser { final String mIface; - final List mCaps; + final NetworkCapabilities mCaps; final String mIpConfig; - final int mTransport; - private static List 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(); + } + + 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); } - final ArrayList capabilities = new ArrayList<>(); 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 @@ public class EthernetTracker { } } - 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 1b0f29dcd6..514563b891 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= gateway= dns= diff --git a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java index 03fb505c10..c1291b0563 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 @@ public class EthernetTrackerTest { .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