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

View File

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

View File

@@ -67,11 +67,6 @@ public class TetheringConfiguration {
private static final String[] EMPTY_STRING_ARRAY = new String[0]; 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. // Default ranges used for the legacy DHCP server.
// USB is 192.168.42.1 and 255.255.255.0 // USB is 192.168.42.1 and 255.255.255.0
// Wifi is 192.168.43.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[] tetherableUsbRegexs;
public final String[] tetherableWifiRegexs; public final String[] tetherableWifiRegexs;
public final String[] tetherableBluetoothRegexs; public final String[] tetherableBluetoothRegexs;
public final int dunCheck;
public final boolean isDunRequired; public final boolean isDunRequired;
public final boolean chooseUpstreamAutomatically; public final boolean chooseUpstreamAutomatically;
public final Collection<Integer> preferredUpstreamIfaceTypes; public final Collection<Integer> preferredUpstreamIfaceTypes;
@@ -116,12 +110,10 @@ public class TetheringConfiguration {
tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs); tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs); tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
dunCheck = checkDunRequired(ctx); isDunRequired = checkDunRequired(ctx);
configLog.log("DUN check returned: " + dunCheckString(dunCheck));
chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic); chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic);
preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, dunCheck); preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
isDunRequired = preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN);
legacyDhcpRanges = getLegacyDhcpRanges(res); legacyDhcpRanges = getLegacyDhcpRanges(res);
defaultIPv4DNS = copy(DEFAULT_IPV4_DNS); defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
@@ -230,53 +222,43 @@ public class TetheringConfiguration {
return upstreamNames; 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); 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) { private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
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) {
final int[] ifaceTypes = res.getIntArray(config_tether_upstream_types); final int[] ifaceTypes = res.getIntArray(config_tether_upstream_types);
final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length); final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
for (int i : ifaceTypes) { for (int i : ifaceTypes) {
switch (i) { switch (i) {
case TYPE_MOBILE: case TYPE_MOBILE:
case TYPE_MOBILE_HIPRI: case TYPE_MOBILE_HIPRI:
if (dunCheck == DUN_REQUIRED) continue; if (dunRequired) continue;
break; break;
case TYPE_MOBILE_DUN: case TYPE_MOBILE_DUN:
if (dunCheck == DUN_NOT_REQUIRED) continue; if (!dunRequired) continue;
break; break;
} }
upstreamIfaceTypes.add(i); upstreamIfaceTypes.add(i);
} }
// Fix up upstream interface types for DUN or mobile. NOTE: independent // 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 // *always* an upstream, regardless of the upstream interface types
// specified by configuration resources. // specified by configuration resources.
if (dunCheck == DUN_REQUIRED) { if (dunRequired) {
appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_DUN); appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_DUN);
} else if (dunCheck == DUN_NOT_REQUIRED) {
appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE);
appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_HIPRI);
} else { } else {
// Fix upstream interface types for case DUN_UNSPECIFIED.
// Do not modify if a cellular interface type is already present in the // 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 // upstream interface types. Add TYPE_MOBILE and TYPE_MOBILE_HIPRI if no
// cellular interface types are found in the upstream interface types. // cellular interface types are found in the upstream interface types.
if (!(containsOneOf(upstreamIfaceTypes, // This preserves backwards compatibility and prevents the DUN and default
TYPE_MOBILE_DUN, TYPE_MOBILE, TYPE_MOBILE_HIPRI))) { // 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);
upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI); 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.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_NOT_REQUIRED; import static com.android.internal.R.array.config_tether_upstream_types;
import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_REQUIRED;
import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_UNSPECIFIED;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@@ -52,6 +50,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@@ -112,74 +111,103 @@ public class TetheringConfigurationTest {
.thenReturn(new String[]{ "test_wlan\\d" }); .thenReturn(new String[]{ "test_wlan\\d" });
when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs)) when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
.thenReturn(new String[0]); .thenReturn(new String[0]);
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[0]);
.thenReturn(new int[0]);
when(mResources.getStringArray( when(mResources.getStringArray(
com.android.internal.R.array.config_mobile_hotspot_provision_app)) com.android.internal.R.array.config_mobile_hotspot_provision_app))
.thenReturn(new String[0]); .thenReturn(new String[0]);
mContentResolver = new MockContentResolver(); mContentResolver = new MockContentResolver();
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
mHasTelephonyManager = true;
mMockContext = new MockContext(mContext); 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 @Test
public void testDunFromTelephonyManagerMeansDun() { public void testDunFromTelephonyManagerMeansDun() {
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) when(mTelephonyManager.getTetherApnRequired()).thenReturn(true);
.thenReturn(new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI});
mHasTelephonyManager = true;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_REQUIRED);
final TetheringConfiguration cfg = new TetheringConfiguration( final TetheringConfiguration cfgWifi = getTetheringConfiguration(new int[]{TYPE_WIFI});
mMockContext, mLog, INVALID_SUBSCRIPTION_ID); final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
assertTrue(cfg.isDunRequired); new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI});
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN)); final TetheringConfiguration cfgWifiDun = getTetheringConfiguration(
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE)); new int[]{TYPE_WIFI, TYPE_MOBILE_DUN});
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)); final TetheringConfiguration cfgMobileWifiHipriDun = getTetheringConfiguration(
// Just to prove we haven't clobbered Wi-Fi: new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI, TYPE_MOBILE_DUN});
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
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 @Test
public void testDunNotRequiredFromTelephonyManagerMeansNoDun() { public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
.thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
mHasTelephonyManager = true;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_NOT_REQUIRED);
final TetheringConfiguration cfg = new TetheringConfiguration( final TetheringConfiguration cfgWifi = getTetheringConfiguration(new int[]{TYPE_WIFI});
mMockContext, mLog, INVALID_SUBSCRIPTION_ID); final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
assertFalse(cfg.isDunRequired); new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI});
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN)); final TetheringConfiguration cfgWifiDun = getTetheringConfiguration(
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE)); new int[]{TYPE_WIFI, TYPE_MOBILE_DUN});
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)); final TetheringConfiguration cfgWifiMobile = getTetheringConfiguration(
// Just to prove we haven't clobbered Wi-Fi: new int[]{TYPE_WIFI, TYPE_MOBILE});
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI)); 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 String msg;
public void testDunFromUpstreamConfigMeansDun() { // TYPE_MOBILE_DUN should not be present in all of the combinations.
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) // TYPE_WIFI should not be affected.
.thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI}); for (TetheringConfiguration cfg : Arrays.asList(cfgWifi, cfgMobileWifiHipri, cfgWifiDun,
mHasTelephonyManager = false; cfgWifiMobile, cfgWifiHipri, cfgMobileWifiHipriDun)) {
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED); 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 @Test
public void testNoDefinedUpstreamTypesAddsEthernet() { public void testNoDefinedUpstreamTypesAddsEthernet() {
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[]{});
.thenReturn(new int[]{}); when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
mHasTelephonyManager = false;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
final TetheringConfiguration cfg = new TetheringConfiguration( final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID); mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -187,8 +215,10 @@ public class TetheringConfigurationTest {
assertTrue(upstreamIterator.hasNext()); assertTrue(upstreamIterator.hasNext());
assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue()); assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue());
// The following is because the code always adds some kind of mobile // 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, // upstream, be it DUN or, in this case where DUN is NOT required,
// both vanilla and hipri mobile types. // 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()); assertTrue(upstreamIterator.hasNext());
assertEquals(TYPE_MOBILE, upstreamIterator.next().intValue()); assertEquals(TYPE_MOBILE, upstreamIterator.next().intValue());
assertTrue(upstreamIterator.hasNext()); assertTrue(upstreamIterator.hasNext());
@@ -198,10 +228,9 @@ public class TetheringConfigurationTest {
@Test @Test
public void testDefinedUpstreamTypesSansEthernetAddsEthernet() { public void testDefinedUpstreamTypesSansEthernetAddsEthernet() {
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(
.thenReturn(new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI}); new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI});
mHasTelephonyManager = false; when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
final TetheringConfiguration cfg = new TetheringConfiguration( final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID); mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -217,10 +246,9 @@ public class TetheringConfigurationTest {
@Test @Test
public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() { 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}); .thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI});
mHasTelephonyManager = false; when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
final TetheringConfiguration cfg = new TetheringConfiguration( final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID); mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -276,9 +304,7 @@ public class TetheringConfigurationTest {
when(mResourcesForSubId.getStringArray( when(mResourcesForSubId.getStringArray(
com.android.internal.R.array.config_tether_bluetooth_regexs)) com.android.internal.R.array.config_tether_bluetooth_regexs))
.thenReturn(new String[0]); .thenReturn(new String[0]);
when(mResourcesForSubId.getIntArray( when(mResourcesForSubId.getIntArray(config_tether_upstream_types)).thenReturn(new int[0]);
com.android.internal.R.array.config_tether_upstream_types))
.thenReturn(new int[0]);
when(mResourcesForSubId.getStringArray( when(mResourcesForSubId.getStringArray(
com.android.internal.R.array.config_mobile_hotspot_provision_app)) com.android.internal.R.array.config_mobile_hotspot_provision_app))
.thenReturn(PROVISIONING_APP_NAME); .thenReturn(PROVISIONING_APP_NAME);