diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java index ac5857d1c8..c6e8fd631f 100644 --- a/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -442,7 +442,8 @@ public class Tethering { // NOTE: This is always invoked on the mLooper thread. private void updateConfiguration() { mConfig = mDeps.generateTetheringConfiguration(mContext, mLog, mActiveDataSubId); - mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired); + mUpstreamNetworkMonitor.setUpstreamConfig(mConfig.chooseUpstreamAutomatically, + mConfig.isDunRequired); reportConfigurationChanged(mConfig.toStableParcelable()); } @@ -1559,7 +1560,7 @@ public class Tethering { config.preferredUpstreamIfaceTypes); if (ns == null) { if (tryCell) { - mUpstreamNetworkMonitor.registerMobileNetworkRequest(); + mUpstreamNetworkMonitor.setTryCell(true); // We think mobile should be coming up; don't set a retry. } else { sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); @@ -1852,7 +1853,7 @@ public class Tethering { // longer desired, release any mobile requests. final boolean previousUpstreamWanted = updateUpstreamWanted(); if (previousUpstreamWanted && !mUpstreamWanted) { - mUpstreamNetworkMonitor.releaseMobileNetworkRequest(); + mUpstreamNetworkMonitor.setTryCell(false); } break; } diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java index b17065cb78..eb22448a73 100644 --- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java +++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java @@ -60,7 +60,7 @@ import java.util.Set; * Calling #startObserveAllNetworks() to observe all networks. Listening all * networks is necessary while the expression of preferred upstreams remains * a list of legacy connectivity types. In future, this can be revisited. - * Calling #registerMobileNetworkRequest() to bring up mobile DUN/HIPRI network. + * Calling #setTryCell() to request bringing up mobile DUN or HIPRI. * * The methods and data members of this class are only to be accessed and * modified from the tethering main state machine thread. Any other @@ -114,7 +114,14 @@ public class UpstreamNetworkMonitor { private NetworkCallback mListenAllCallback; private NetworkCallback mDefaultNetworkCallback; private NetworkCallback mMobileNetworkCallback; + + /** Whether Tethering has requested a cellular upstream. */ + private boolean mTryCell; + /** Whether the carrier requires DUN. */ private boolean mDunRequired; + /** Whether automatic upstream selection is enabled. */ + private boolean mAutoUpstream; + // Whether the current default upstream is mobile or not. private boolean mIsDefaultCellularUpstream; // The current system default network (not really used yet). @@ -190,23 +197,49 @@ public class UpstreamNetworkMonitor { mNetworkMap.clear(); } - /** Setup or teardown DUN connection according to |dunRequired|. */ - public void updateMobileRequiresDun(boolean dunRequired) { - final boolean valueChanged = (mDunRequired != dunRequired); + private void reevaluateUpstreamRequirements(boolean tryCell, boolean autoUpstream, + boolean dunRequired) { + final boolean mobileRequestWasRequired = mTryCell && (mDunRequired || !mAutoUpstream); + final boolean mobileRequestIsRequired = tryCell && (dunRequired || !autoUpstream); + final boolean dunRequiredChanged = (mDunRequired != dunRequired); + + mTryCell = tryCell; mDunRequired = dunRequired; - if (valueChanged && mobileNetworkRequested()) { + mAutoUpstream = autoUpstream; + + if (dunRequiredChanged && mobileNetworkRequested()) { releaseMobileNetworkRequest(); registerMobileNetworkRequest(); } } + /** + * Informs UpstreamNetworkMonitor that a cellular upstream is desired. + * + * This may result in filing a NetworkRequest for DUN if it is required, or for MOBILE_HIPRI if + * automatic upstream selection is disabled and MOBILE_HIPRI is the preferred upstream. + */ + public void setTryCell(boolean tryCell) { + reevaluateUpstreamRequirements(tryCell, mAutoUpstream, mDunRequired); + if (tryCell) { + registerMobileNetworkRequest(); + } else { + releaseMobileNetworkRequest(); + } + } + + /** Informs UpstreamNetworkMonitor of upstream configuration parameters. */ + public void setUpstreamConfig(boolean autoUpstream, boolean dunRequired) { + reevaluateUpstreamRequirements(mTryCell, autoUpstream, dunRequired); + } + /** Whether mobile network is requested. */ public boolean mobileNetworkRequested() { return (mMobileNetworkCallback != null); } /** Request mobile network if mobile upstream is permitted. */ - public void registerMobileNetworkRequest() { + private void registerMobileNetworkRequest() { if (!isCellularUpstreamPermitted()) { mLog.i("registerMobileNetworkRequest() is not permitted"); releaseMobileNetworkRequest(); @@ -248,7 +281,7 @@ public class UpstreamNetworkMonitor { } /** Release mobile network request. */ - public void releaseMobileNetworkRequest() { + private void releaseMobileNetworkRequest() { if (mMobileNetworkCallback == null) return; cm().unregisterNetworkCallback(mMobileNetworkCallback); 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 0611086448..d5c7add31c 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -1101,7 +1101,7 @@ public class TetheringTest { sendUsbBroadcast(true, true, true, TETHERING_USB); mLooper.dispatchAll(); inOrder.verify(mUpstreamNetworkMonitor).startObserveAllNetworks(); - inOrder.verify(mUpstreamNetworkMonitor).registerMobileNetworkRequest(); + inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true); // Pretend cellular connected and expect the upstream to be set. TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState()); @@ -1251,7 +1251,7 @@ public class TetheringTest { verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks(); // In tethering mode, in the default configuration, an explicit request // for a mobile network is also made. - verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest(); + verify(mUpstreamNetworkMonitor, times(1)).setTryCell(true); // There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_TETHERED verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE); verify(mNotificationUpdater, times(1)).onDownstreamChanged(eq(1 << TETHERING_WIFI)); diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java index 7d735fc48f..4376b61a48 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java @@ -134,9 +134,9 @@ public class UpstreamNetworkMonitorTest { assertTrue(mCM.hasNoCallbacks()); assertFalse(mUNM.mobileNetworkRequested()); - mUNM.updateMobileRequiresDun(true); + mUNM.setUpstreamConfig(false /* autoUpstream */, true /* dunRequired */); assertTrue(mCM.hasNoCallbacks()); - mUNM.updateMobileRequiresDun(false); + mUNM.setUpstreamConfig(false /* autoUpstream */, false /* dunRequired */); assertTrue(mCM.hasNoCallbacks()); } @@ -187,11 +187,11 @@ public class UpstreamNetworkMonitorTest { assertFalse(mUNM.mobileNetworkRequested()); assertEquals(0, mCM.requested.size()); - mUNM.updateMobileRequiresDun(false); + mUNM.setUpstreamConfig(false /* autoUpstream */, false /* dunRequired */); assertFalse(mUNM.mobileNetworkRequested()); assertEquals(0, mCM.requested.size()); - mUNM.registerMobileNetworkRequest(); + mUNM.setTryCell(true); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); assertFalse(isDunRequested()); @@ -212,8 +212,8 @@ public class UpstreamNetworkMonitorTest { assertFalse(mUNM.mobileNetworkRequested()); assertEquals(0, mCM.requested.size()); - mUNM.updateMobileRequiresDun(true); - mUNM.registerMobileNetworkRequest(); + mUNM.setUpstreamConfig(false /* autoUpstream */, true /* dunRequired */); + mUNM.setTryCell(true); verify(mCM, times(1)).requestNetwork( any(NetworkRequest.class), anyInt(), anyInt(), any(Handler.class), any(NetworkCallback.class)); @@ -223,9 +223,9 @@ public class UpstreamNetworkMonitorTest { assertTrue(isDunRequested()); // Try a few things that must not result in any state change. - mUNM.registerMobileNetworkRequest(); - mUNM.updateMobileRequiresDun(true); - mUNM.registerMobileNetworkRequest(); + mUNM.setTryCell(true); + mUNM.setUpstreamConfig(false /* autoUpstream */, true /* dunRequired */); + mUNM.setTryCell(true); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); @@ -246,11 +246,11 @@ public class UpstreamNetworkMonitorTest { assertFalse(mUNM.mobileNetworkRequested()); assertEquals(0, mCM.requested.size()); - mUNM.updateMobileRequiresDun(true); + mUNM.setUpstreamConfig(false /* autoUpstream */, true /* dunRequired */); assertFalse(mUNM.mobileNetworkRequested()); assertEquals(0, mCM.requested.size()); - mUNM.registerMobileNetworkRequest(); + mUNM.setTryCell(true); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); assertTrue(isDunRequested()); @@ -265,18 +265,18 @@ public class UpstreamNetworkMonitorTest { mUNM.startObserveAllNetworks(); // Test going from no-DUN to DUN correctly re-registers callbacks. - mUNM.updateMobileRequiresDun(false); - mUNM.registerMobileNetworkRequest(); + mUNM.setUpstreamConfig(false /* autoUpstream */, false /* dunRequired */); + mUNM.setTryCell(true); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); assertFalse(isDunRequested()); - mUNM.updateMobileRequiresDun(true); + mUNM.setUpstreamConfig(false /* autoUpstream */, true /* dunRequired */); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); assertTrue(isDunRequested()); // Test going from DUN to no-DUN correctly re-registers callbacks. - mUNM.updateMobileRequiresDun(false); + mUNM.setUpstreamConfig(false /* autoUpstream */, false /* dunRequired */); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); assertFalse(isDunRequested()); @@ -309,14 +309,14 @@ public class UpstreamNetworkMonitorTest { preferredTypes.add(TYPE_MOBILE_DUN); // This is coupled with preferred types in TetheringConfiguration. - mUNM.updateMobileRequiresDun(true); + mUNM.setUpstreamConfig(false /* autoUpstream */, true /* dunRequired */); // DUN is available, but only use regular cell: no upstream selected. assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); preferredTypes.remove(TYPE_MOBILE_DUN); // No WiFi, but our preferred flavour of cell is up. preferredTypes.add(TYPE_MOBILE_HIPRI); // This is coupled with preferred types in TetheringConfiguration. - mUNM.updateMobileRequiresDun(false); + mUNM.setUpstreamConfig(false /* autoUpstream */, false /* dunRequired */); assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI, mUNM.selectPreferredUpstreamType(preferredTypes)); // Check to see we filed an explicit request. @@ -341,7 +341,7 @@ public class UpstreamNetworkMonitorTest { preferredTypes.remove(TYPE_MOBILE_HIPRI); preferredTypes.add(TYPE_MOBILE_DUN); // This is coupled with preferred types in TetheringConfiguration. - mUNM.updateMobileRequiresDun(true); + mUNM.setUpstreamConfig(false /* autoUpstream */, true /* dunRequired */); assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, DUN_CAPABILITIES); @@ -373,7 +373,7 @@ public class UpstreamNetworkMonitorTest { public void testGetCurrentPreferredUpstream() throws Exception { mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); - mUNM.updateMobileRequiresDun(false); + mUNM.setUpstreamConfig(false /* autoUpstream */, false /* dunRequired */); // [0] Mobile connects, DUN not required -> mobile selected. final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES); @@ -396,7 +396,7 @@ public class UpstreamNetworkMonitorTest { assertEquals(wifiAgent.networkId, mUNM.getCurrentPreferredUpstream().network); // [4] DUN required, no other changes -> WiFi still selected - mUNM.updateMobileRequiresDun(true); + mUNM.setUpstreamConfig(false /* autoUpstream */, true /* dunRequired */); assertEquals(wifiAgent.networkId, mUNM.getCurrentPreferredUpstream().network); // [5] WiFi no longer validated, mobile becomes default, DUN required -> null selected.