Merge "Check if DUN APN exists to decide isDunRequired"

This commit is contained in:
Mark Chien
2019-03-03 06:53:47 +00:00
committed by Gerrit Code Review
4 changed files with 113 additions and 111 deletions

View File

@@ -477,22 +477,16 @@
- the return value of TelephonyManager.getTetherApnRequired()
determines how the array is further modified:
* DUN_REQUIRED
TYPE_MOBILE is removed (if present)
TYPE_MOBILE_HIPRI is removed (if present)
TYPE_MOBILE_DUN is appended (if not already present)
* TRUE (DUN REQUIRED).
TYPE_MOBILE is removed (if present).
TYPE_MOBILE_HIPRI is removed (if present).
TYPE_MOBILE_DUN is appended (if not already present).
* DUN_NOT_REQUIRED
TYPE_MOBILE_DUN is removed (if present)
TYPE_MOBILE is appended (if not already present)
TYPE_MOBILE_HIPRI is appended (if not already present)
* DUN_UNSPECIFIED
if any of TYPE_MOBILE{,_DUN,_HIPRI} are present:
change nothing
else:
TYPE_MOBILE is appended
TYPE_MOBILE_HIPRI is appended
* FALSE (DUN NOT REQUIRED).
TYPE_MOBILE_DUN is removed (if present).
If both of TYPE_MOBILE{,_HIPRI} are not present:
TYPE_MOBILE is appended.
TYPE_MOBILE_HIPRI is appended.
For other changes applied to this list, now and in the future, see
com.android.server.connectivity.tethering.TetheringConfiguration.

View File

@@ -289,8 +289,8 @@ public class Tethering extends BaseNetworkObserver {
}
private void maybeUpdateConfiguration() {
final int dunCheck = TetheringConfiguration.checkDunRequired(mContext);
if (dunCheck == mConfig.dunCheck) return;
final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext);
if (isDunRequired == mConfig.isDunRequired) return;
updateConfiguration();
}

View File

@@ -67,11 +67,6 @@ public class TetheringConfiguration {
private static final String[] EMPTY_STRING_ARRAY = new String[0];
@VisibleForTesting
public static final int DUN_NOT_REQUIRED = 0;
public static final int DUN_REQUIRED = 1;
public static final int DUN_UNSPECIFIED = 2;
// Default ranges used for the legacy DHCP server.
// USB is 192.168.42.1 and 255.255.255.0
// Wifi is 192.168.43.1 and 255.255.255.0
@@ -90,7 +85,6 @@ public class TetheringConfiguration {
public final String[] tetherableUsbRegexs;
public final String[] tetherableWifiRegexs;
public final String[] tetherableBluetoothRegexs;
public final int dunCheck;
public final boolean isDunRequired;
public final boolean chooseUpstreamAutomatically;
public final Collection<Integer> preferredUpstreamIfaceTypes;
@@ -116,12 +110,10 @@ public class TetheringConfiguration {
tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
dunCheck = checkDunRequired(ctx);
configLog.log("DUN check returned: " + dunCheckString(dunCheck));
isDunRequired = checkDunRequired(ctx);
chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic);
preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, dunCheck);
isDunRequired = preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN);
preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
legacyDhcpRanges = getLegacyDhcpRanges(res);
defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
@@ -230,53 +222,43 @@ public class TetheringConfiguration {
return upstreamNames;
}
public static int checkDunRequired(Context ctx) {
/** Check whether dun is required. */
public static boolean checkDunRequired(Context ctx) {
final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
return (tm != null) ? tm.getTetherApnRequired() : DUN_UNSPECIFIED;
return (tm != null) ? tm.getTetherApnRequired() : false;
}
private static String dunCheckString(int dunCheck) {
switch (dunCheck) {
case DUN_NOT_REQUIRED: return "DUN_NOT_REQUIRED";
case DUN_REQUIRED: return "DUN_REQUIRED";
case DUN_UNSPECIFIED: return "DUN_UNSPECIFIED";
default:
return String.format("UNKNOWN (%s)", dunCheck);
}
}
private static Collection<Integer> getUpstreamIfaceTypes(Resources res, int dunCheck) {
private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
final int[] ifaceTypes = res.getIntArray(config_tether_upstream_types);
final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
for (int i : ifaceTypes) {
switch (i) {
case TYPE_MOBILE:
case TYPE_MOBILE_HIPRI:
if (dunCheck == DUN_REQUIRED) continue;
if (dunRequired) continue;
break;
case TYPE_MOBILE_DUN:
if (dunCheck == DUN_NOT_REQUIRED) continue;
if (!dunRequired) continue;
break;
}
upstreamIfaceTypes.add(i);
}
// Fix up upstream interface types for DUN or mobile. NOTE: independent
// of the value of |dunCheck|, cell data of one form or another is
// of the value of |dunRequired|, cell data of one form or another is
// *always* an upstream, regardless of the upstream interface types
// specified by configuration resources.
if (dunCheck == DUN_REQUIRED) {
if (dunRequired) {
appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_DUN);
} else if (dunCheck == DUN_NOT_REQUIRED) {
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 (!(containsOneOf(upstreamIfaceTypes,
TYPE_MOBILE_DUN, TYPE_MOBILE, TYPE_MOBILE_HIPRI))) {
// This preserves backwards compatibility and prevents the DUN and default
// mobile types incorrectly appearing together, which could happen on
// previous releases in the common case where checkDunRequired returned
// DUN_UNSPECIFIED.
if (!containsOneOf(upstreamIfaceTypes, TYPE_MOBILE, TYPE_MOBILE_HIPRI)) {
upstreamIfaceTypes.add(TYPE_MOBILE);
upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
}

View File

@@ -24,9 +24,7 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_NOT_REQUIRED;
import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_REQUIRED;
import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_UNSPECIFIED;
import static com.android.internal.R.array.config_tether_upstream_types;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -52,6 +50,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.Iterator;
@RunWith(AndroidJUnit4.class)
@@ -112,74 +111,103 @@ public class TetheringConfigurationTest {
.thenReturn(new String[]{ "test_wlan\\d" });
when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
.thenReturn(new String[0]);
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
.thenReturn(new int[0]);
when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[0]);
when(mResources.getStringArray(
com.android.internal.R.array.config_mobile_hotspot_provision_app))
.thenReturn(new String[0]);
mContentResolver = new MockContentResolver();
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
mHasTelephonyManager = true;
mMockContext = new MockContext(mContext);
}
private TetheringConfiguration getTetheringConfiguration(int[] legacyTetherUpstreamTypes) {
when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(
legacyTetherUpstreamTypes);
return new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
}
@Test
public void testNoTelephonyManagerMeansNoDun() {
mHasTelephonyManager = false;
final TetheringConfiguration cfg = getTetheringConfiguration(
new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
assertFalse(cfg.isDunRequired);
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
// Just to prove we haven't clobbered Wi-Fi:
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
}
@Test
public void testDunFromTelephonyManagerMeansDun() {
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
.thenReturn(new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI});
mHasTelephonyManager = true;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_REQUIRED);
when(mTelephonyManager.getTetherApnRequired()).thenReturn(true);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(cfg.isDunRequired);
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
// Just to prove we haven't clobbered Wi-Fi:
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
final TetheringConfiguration cfgWifi = getTetheringConfiguration(new int[]{TYPE_WIFI});
final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI});
final TetheringConfiguration cfgWifiDun = getTetheringConfiguration(
new int[]{TYPE_WIFI, TYPE_MOBILE_DUN});
final TetheringConfiguration cfgMobileWifiHipriDun = getTetheringConfiguration(
new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI, TYPE_MOBILE_DUN});
for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri,
cfgWifiDun, cfgMobileWifiHipriDun)) {
String msg = "config=" + cfg.toString();
assertTrue(msg, cfg.isDunRequired);
assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
assertFalse(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
assertFalse(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
// Just to prove we haven't clobbered Wi-Fi:
assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
}
}
@Test
public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
.thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
mHasTelephonyManager = true;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_NOT_REQUIRED);
when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertFalse(cfg.isDunRequired);
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
// Just to prove we haven't clobbered Wi-Fi:
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
}
final TetheringConfiguration cfgWifi = getTetheringConfiguration(new int[]{TYPE_WIFI});
final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI});
final TetheringConfiguration cfgWifiDun = getTetheringConfiguration(
new int[]{TYPE_WIFI, TYPE_MOBILE_DUN});
final TetheringConfiguration cfgWifiMobile = getTetheringConfiguration(
new int[]{TYPE_WIFI, TYPE_MOBILE});
final TetheringConfiguration cfgWifiHipri = getTetheringConfiguration(
new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI});
final TetheringConfiguration cfgMobileWifiHipriDun = getTetheringConfiguration(
new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI, TYPE_MOBILE_DUN});
@Test
public void testDunFromUpstreamConfigMeansDun() {
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
.thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
mHasTelephonyManager = false;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
String msg;
// TYPE_MOBILE_DUN should not be present in all of the combinations.
// TYPE_WIFI should not be affected.
for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri, cfgWifiDun,
cfgWifiMobile, cfgWifiHipri, cfgMobileWifiHipriDun)) {
msg = "config=" + cfg.toString();
assertFalse(msg, cfg.isDunRequired);
assertFalse(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
}
for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri, cfgWifiDun,
cfgMobileWifiHipriDun)) {
msg = "config=" + cfg.toString();
assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
assertTrue(msg, cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
}
msg = "config=" + cfgWifiMobile.toString();
assertTrue(msg, cfgWifiMobile.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
assertFalse(msg, cfgWifiMobile.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
msg = "config=" + cfgWifiHipri.toString();
assertFalse(msg, cfgWifiHipri.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
assertTrue(msg, cfgWifiHipri.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(cfg.isDunRequired);
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
// Just to prove we haven't clobbered Wi-Fi:
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
// Check that we have not added new cellular interface types
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);
when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[]{});
when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -187,8 +215,10 @@ public class TetheringConfigurationTest {
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.
// upstream, be it DUN or, in this case where DUN is NOT required,
// make sure there is at least one of MOBILE or HIPRI. With the empty
// list of the configuration in this test, it will always add both
// MOBILE and HIPRI, in that order.
assertTrue(upstreamIterator.hasNext());
assertEquals(TYPE_MOBILE, upstreamIterator.next().intValue());
assertTrue(upstreamIterator.hasNext());
@@ -198,10 +228,9 @@ public class TetheringConfigurationTest {
@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);
when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(
new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI});
when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -217,10 +246,9 @@ public class TetheringConfigurationTest {
@Test
public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() {
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
when(mResources.getIntArray(config_tether_upstream_types))
.thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI});
mHasTelephonyManager = false;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -276,9 +304,7 @@ public class TetheringConfigurationTest {
when(mResourcesForSubId.getStringArray(
com.android.internal.R.array.config_tether_bluetooth_regexs))
.thenReturn(new String[0]);
when(mResourcesForSubId.getIntArray(
com.android.internal.R.array.config_tether_upstream_types))
.thenReturn(new int[0]);
when(mResourcesForSubId.getIntArray(config_tether_upstream_types)).thenReturn(new int[0]);
when(mResourcesForSubId.getStringArray(
com.android.internal.R.array.config_mobile_hotspot_provision_app))
.thenReturn(PROVISIONING_APP_NAME);