diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java index 07fce08995..bb9b6fbeaa 100644 --- a/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -1533,16 +1533,28 @@ public class Tethering { return mConfig; } - boolean hasTetherableConfiguration() { - final TetheringConfiguration cfg = mConfig; - final boolean hasDownstreamConfiguration = - (cfg.tetherableUsbRegexs.length != 0) - || (cfg.tetherableWifiRegexs.length != 0) - || (cfg.tetherableBluetoothRegexs.length != 0); - final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty() - || cfg.chooseUpstreamAutomatically; + boolean hasAnySupportedDownstream() { + if ((mConfig.tetherableUsbRegexs.length != 0) + || (mConfig.tetherableWifiRegexs.length != 0) + || (mConfig.tetherableBluetoothRegexs.length != 0)) { + return true; + } - return hasDownstreamConfiguration && hasUpstreamConfiguration; + // Before T, isTetheringSupported would return true if wifi, usb and bluetooth tethering are + // disabled (whole tethering settings would be hidden). This means tethering would also not + // support wifi p2p, ethernet tethering and mirrorlink. This is wrong but probably there are + // some devices in the field rely on this to disable tethering entirely. + if (!SdkLevel.isAtLeastT()) return false; + + return (mConfig.tetherableWifiP2pRegexs.length != 0) + || (mConfig.tetherableNcmRegexs.length != 0) + || isEthernetSupported(); + } + + // TODO: using EtherentManager new API to check whether ethernet is supported when the API is + // ready to use. + private boolean isEthernetSupported() { + return mContext.getSystemService(Context.ETHERNET_SERVICE) != null; } void setUsbTethering(boolean enable, IIntResultListener listener) { @@ -2463,7 +2475,7 @@ public class Tethering { final boolean tetherEnabledInSettings = tetherSupported && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); - return tetherEnabledInSettings && hasTetherableConfiguration() + return tetherEnabledInSettings && hasAnySupportedDownstream() && !isProvisioningNeededButUnavailable(); } diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java index c1a747e673..9224213f0e 100644 --- a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java +++ b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java @@ -93,13 +93,6 @@ public abstract class TetheringDependencies { */ public abstract IpServer.Dependencies getIpServerDependencies(); - /** - * Indicates whether tethering is supported on the device. - */ - public boolean isTetheringSupported() { - return true; - } - /** * Get a reference to the EntitlementManager to be used by tethering. */ diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java index ae5d38987a..03887589ef 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -297,6 +297,7 @@ public class TetheringTest { private TetheredInterfaceCallbackShim mTetheredInterfaceCallbackShim; private TestConnectivityManager mCm; + private boolean mForceEthernetServiceUnavailable = false; private class TestContext extends BroadcastInterceptingContext { TestContext(Context base) { @@ -331,7 +332,11 @@ public class TetheringTest { if (Context.USER_SERVICE.equals(name)) return mUserManager; if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager; if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; - if (Context.ETHERNET_SERVICE.equals(name)) return mEm; + if (Context.ETHERNET_SERVICE.equals(name)) { + if (mForceEthernetServiceUnavailable) return null; + + return mEm; + } return super.getSystemService(name); } @@ -451,11 +456,6 @@ public class TetheringTest { return mEntitleMgr; } - @Override - public boolean isTetheringSupported() { - return true; - } - @Override public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log, int subId) { @@ -680,6 +680,7 @@ public class TetheringTest { .thenReturn(new String[] {TEST_BT_REGEX}); when(mResources.getStringArray(R.array.config_tether_ncm_regexs)) .thenReturn(new String[] {TEST_NCM_REGEX}); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)).thenReturn(true); when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn( new int[] {TYPE_WIFI, TYPE_MOBILE_DUN}); when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true); @@ -2834,6 +2835,55 @@ public class TetheringTest { runDualStackUsbTethering(TEST_RNDIS_IFNAME); runStopUSBTethering(); } + + @Test + public void testTetheringSupported() throws Exception { + setTetheringSupported(true /* supported */); + updateConfigAndVerifySupported(true /* supported */); + + // Could disable tethering supported by settings. + Settings.Global.putInt(mContentResolver, Settings.Global.TETHER_SUPPORTED, 0); + updateConfigAndVerifySupported(false /* supported */); + + // Could disable tethering supported by user restriction. + setTetheringSupported(true /* supported */); + when(mUserManager.hasUserRestriction( + UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(true); + updateConfigAndVerifySupported(false /* supported */); + + // Tethering is supported if it has any supported downstream. + setTetheringSupported(true /* supported */); + when(mResources.getStringArray(R.array.config_tether_usb_regexs)) + .thenReturn(new String[0]); + updateConfigAndVerifySupported(true /* supported */); + when(mResources.getStringArray(R.array.config_tether_wifi_regexs)) + .thenReturn(new String[0]); + updateConfigAndVerifySupported(true /* supported */); + + + if (isAtLeastT()) { + when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs)) + .thenReturn(new String[0]); + updateConfigAndVerifySupported(true /* supported */); + when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs)) + .thenReturn(new String[0]); + updateConfigAndVerifySupported(true /* supported */); + when(mResources.getStringArray(R.array.config_tether_ncm_regexs)) + .thenReturn(new String[0]); + updateConfigAndVerifySupported(true /* supported */); + mForceEthernetServiceUnavailable = true; + updateConfigAndVerifySupported(false /* supported */); + } else { + when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs)) + .thenReturn(new String[0]); + updateConfigAndVerifySupported(false /* supported */); + } + } + + private void updateConfigAndVerifySupported(boolean supported) { + sendConfigurationChanged(); + assertEquals(supported, mTethering.isTetheringSupported()); + } // TODO: Test that a request for hotspot mode doesn't interfere with an // already operating tethering mode interface. }