From 0e61baa0ac83e580429217f8394e1790d6510158 Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Thu, 9 Mar 2017 11:44:11 +0900 Subject: Always allow Ethernet to be an upstream If there are any upstream types defined at all, make sure that either TYPE_ETHERNET is included somewhere within the sorted list or force it to be at the front. Test: as follows - built - flashed - booted - runtest frameworks-net passes Bug: 32163131 Bug: 36076442 Change-Id: Ie61d1358f73d518de23f6ca48ca2765ca14a1067 --- .../tethering/TetheringConfiguration.java | 39 +++++++++----- .../tethering/TetheringConfigurationTest.java | 60 ++++++++++++++++++++++ 2 files changed, 87 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java index 651de8910925..9b034aef1e95 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java @@ -17,6 +17,7 @@ package com.android.server.connectivity.tethering; import static android.content.Context.TELEPHONY_SERVICE; +import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; @@ -208,29 +209,26 @@ public class TetheringConfiguration { // *always* an upstream, regardless of the upstream interface types // specified by configuration resources. if (dunCheck == DUN_REQUIRED) { - if (!upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)) { - upstreamIfaceTypes.add(TYPE_MOBILE_DUN); - } + appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_DUN); } else if (dunCheck == DUN_NOT_REQUIRED) { - if (!upstreamIfaceTypes.contains(TYPE_MOBILE)) { - upstreamIfaceTypes.add(TYPE_MOBILE); - } - if (!upstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)) { - upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI); - } + appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE); + appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_HIPRI); } else { // Fix upstream interface types for case DUN_UNSPECIFIED. // Do not modify if a cellular interface type is already present in the // upstream interface types. Add TYPE_MOBILE and TYPE_MOBILE_HIPRI if no // cellular interface types are found in the upstream interface types. - if (!(upstreamIfaceTypes.contains(TYPE_MOBILE_DUN) - || upstreamIfaceTypes.contains(TYPE_MOBILE) - || upstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI))) { + if (!(containsOneOf(upstreamIfaceTypes, + TYPE_MOBILE_DUN, TYPE_MOBILE, TYPE_MOBILE_HIPRI))) { upstreamIfaceTypes.add(TYPE_MOBILE); upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI); } } + // Always make sure our good friend Ethernet is present. + // TODO: consider unilaterally forcing this at the front. + prependIfNotPresent(upstreamIfaceTypes, TYPE_ETHERNET); + return upstreamIfaceTypes; } @@ -253,4 +251,21 @@ public class TetheringConfiguration { private static String[] copy(String[] strarray) { return Arrays.copyOf(strarray, strarray.length); } + + private static void prependIfNotPresent(ArrayList list, int value) { + if (list.contains(value)) return; + list.add(0, value); + } + + private static void appendIfNotPresent(ArrayList list, int value) { + if (list.contains(value)) return; + list.add(value); + } + + private static boolean containsOneOf(ArrayList list, Integer... values) { + for (Integer value : values) { + if (list.contains(value)) return true; + } + return false; + } } diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java index 27be135cb796..b68f203d869f 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java +++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java @@ -16,6 +16,7 @@ package com.android.server.connectivity.tethering; +import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; @@ -38,6 +39,8 @@ import android.telephony.TelephonyManager; import com.android.internal.util.test.BroadcastInterceptingContext; +import java.util.Iterator; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -134,4 +137,61 @@ public class TetheringConfigurationTest { assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE)); assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)); } + + @Test + public void testNoDefinedUpstreamTypesAddsEthernet() { + when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) + .thenReturn(new int[]{}); + mHasTelephonyManager = false; + when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED); + + final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog); + final Iterator upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator(); + assertTrue(upstreamIterator.hasNext()); + assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue()); + // The following is because the code always adds some kind of mobile + // upstream, be it DUN or, in this case where we use DUN_UNSPECIFIED, + // both vanilla and hipri mobile types. + assertTrue(upstreamIterator.hasNext()); + assertEquals(TYPE_MOBILE, upstreamIterator.next().intValue()); + assertTrue(upstreamIterator.hasNext()); + assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue()); + assertFalse(upstreamIterator.hasNext()); + } + + @Test + public void testDefinedUpstreamTypesSansEthernetAddsEthernet() { + when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) + .thenReturn(new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI}); + mHasTelephonyManager = false; + when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED); + + final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog); + final Iterator upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator(); + assertTrue(upstreamIterator.hasNext()); + assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue()); + assertTrue(upstreamIterator.hasNext()); + assertEquals(TYPE_WIFI, upstreamIterator.next().intValue()); + assertTrue(upstreamIterator.hasNext()); + assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue()); + assertFalse(upstreamIterator.hasNext()); + } + + @Test + public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() { + when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) + .thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI}); + mHasTelephonyManager = false; + when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED); + + final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog); + final Iterator upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator(); + assertTrue(upstreamIterator.hasNext()); + assertEquals(TYPE_WIFI, upstreamIterator.next().intValue()); + assertTrue(upstreamIterator.hasNext()); + assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue()); + assertTrue(upstreamIterator.hasNext()); + assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue()); + assertFalse(upstreamIterator.hasNext()); + } } -- cgit v1.2.3-59-g8ed1b