From ecfe7108059c922c3c28d1212c3b04abb9fb6ba2 Mon Sep 17 00:00:00 2001 From: Hungming Chen Date: Wed, 21 Dec 2022 20:16:39 +0800 Subject: [PATCH 1/3] TetheringTest: separate setup func from chooseDunUpstreamTestCommon Prepare to share setup function to more dun network tests. No operation is changed. Bug: 257408654 Test: TetheringTest Change-Id: I29f08d8bc3cf83aa9d03f5d2819a1c67466b7bcc --- .../networkstack/tethering/TetheringTest.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) 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 a8d886b281..e6e363503d 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -1425,8 +1425,7 @@ public class TetheringTest { verifyDisableTryCellWhenTetheringStop(inOrder); } - private void chooseDunUpstreamTestCommon(final boolean automatic, InOrder inOrder, - TestNetworkAgent mobile, TestNetworkAgent wifi, TestNetworkAgent dun) throws Exception { + private NetworkCallback setupDunUpstreamTest(final boolean automatic, InOrder inOrder) { when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(automatic); when(mTelephonyManager.isTetheringApnRequired()).thenReturn(true); sendConfigurationChanged(); @@ -1439,8 +1438,14 @@ public class TetheringTest { inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true); ArgumentCaptor captor = ArgumentCaptor.forClass(NetworkCallback.class); inOrder.verify(mCm).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(), - captor.capture()); - final NetworkCallback dunNetworkCallback1 = captor.getValue(); + captor.capture() /* DUN network callback */); + + return captor.getValue(); + } + + private void chooseDunUpstreamTestCommon(final boolean automatic, InOrder inOrder, + TestNetworkAgent mobile, TestNetworkAgent wifi, TestNetworkAgent dun) throws Exception { + final NetworkCallback dunNetworkCallback1 = setupDunUpstreamTest(automatic, inOrder); // Pretend cellular connected and expect the upstream to be set. mobile.fakeConnect(); From 4c8c35748f33dd07e69e632d6a9abb1f0a4d46e2 Mon Sep 17 00:00:00 2001 From: Hungming Chen Date: Fri, 2 Dec 2022 21:09:00 +0800 Subject: [PATCH 2/3] Test: add tests to testChooseDunUpstreamByAutomaticMode_* Add dun network test cases as follows. Overall test coverage: - testChooseDunUpstreamByAutomaticMode (original): common, test#1, test#2 - testChooseDunUpstreamByAutomaticMode_defaultNetworkWifi (new): test#3, test#4 - testChooseDunUpstreamByAutomaticMode_loseDefaultNetworkWifi (new): test#5 - testChooseDunUpstreamByAutomaticMode_defaultNetworkCell (new): test#5, test#7 - testChooseDunUpstreamByAutomaticMode_loseAndRegainDun (new): test#8 - testChooseDunUpstreamByAutomaticMode_switchDefaultFromWifiToCell (new): test#9, test#10 Overall test cases: +-------+-------+-------+-------+-------+ | Test | WiFi | Cellu | Dun | Expec | | Case | | alr | | ted | | # | | | | Upstr | | | | | | eam | +-------+-------+-------+-------+-------+ | - | | | | - | --+ +-------+-------+-------+-------+-------+ | | - | | V | | - | | +-------+-------+-------+-------+-------+ | Implemented | - | | V | O | Dun | +-- in chooseDun +-------+-------+-------+-------+-------+ | UpstreamTest | - | V | O | O | WiFi | | Common() +-------+-------+-------+-------+-------+ | | - | V | O | | WiFi | --+ +-------+-------+-------+-------+-------+ | | O | V | | - | | 1 +-------+-------+-------+-------+ | | O | V | O | Dun | +-------+-------+-------+-------+-------+ | | O | V | | - | | 2 +-------+-------+-------+-------+ | | O | V | O | Dun | +-------+-------+-------+-------+-------+ | 3 | V | O | | WiFi | (new) +-------+-------+-------+-------+-------+ | 4 | V | | | WiFi | (new) +-------+-------+-------+-------+-------+ | 5 | | | O | Dun | (new) +-------+-------+-------+-------+-------+ | 6 | | V | O | Dun | (new) +-------+-------+-------+-------+-------+ | 7 | | | O | Dun | (new) +-------+-------+-------+-------+-------+ | | | | | - | (new) | 8 +-------+-------+-------+-------+ | | | | O | Dun | +-------+-------+-------+-------+-------+ | | V | | O | WiFi | (new) | 9 +-------+-------+-------+-------+ | | V | | | WiFi | +-------+-------+-------+-------+-------+ | | O | V | | - | (new) | 10 +-------+-------+-------+-------+ | | O | V | O | Dun | +-------+-------+-------+-------+-------+ Annotation: 1. "V" means that the given network is connected and it is default network. 2. "O" means that the given network is connected and it is not default network. Bug: 257408654 Test: atest ConnectivityCoverageTests Change-Id: Ie7beda1a8fcfd2a3f2600ca601f58d869144d275 --- .../networkstack/tethering/TetheringTest.java | 381 +++++++++++++++++- 1 file changed, 367 insertions(+), 14 deletions(-) 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 e6e363503d..7f982f36bb 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -82,6 +82,8 @@ import static com.android.testutils.TestPermissionUtil.runAsShell; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; @@ -179,6 +181,7 @@ import android.test.mock.MockContentResolver; import android.util.ArraySet; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -1337,6 +1340,131 @@ public class TetheringTest { verifyDisableTryCellWhenTetheringStop(inOrder); } + private void verifyWifiUpstreamAndUnregisterDunCallback(@NonNull final InOrder inOrder, + @NonNull final TestNetworkAgent wifi, + @NonNull final NetworkCallback currentDunCallack) throws Exception { + assertNotNull(currentDunCallack); + + inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false); + inOrder.verify(mCm).unregisterNetworkCallback(eq(currentDunCallack)); + inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId); + inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any()); + } + + @Nullable + private NetworkCallback verifyDunUpstream(@NonNull final InOrder inOrder, + @NonNull final TestNetworkAgent dun, final boolean needToRequestNetwork) + throws Exception { + inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true); + ArgumentCaptor captor = ArgumentCaptor.forClass(NetworkCallback.class); + NetworkCallback dunNetworkCallback = null; + if (needToRequestNetwork) { + inOrder.verify(mCm).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(), + captor.capture()); + dunNetworkCallback = captor.getValue(); + } + inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null); + final Runnable doDispatchAll = () -> mLooper.dispatchAll(); + dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll); + mLooper.dispatchAll(); + inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId); + + if (needToRequestNetwork) { + assertNotNull(dunNetworkCallback); + } else { + assertNull(dunNetworkCallback); + } + + return dunNetworkCallback; + } + + // Overall test coverage: + // - verifyChooseDunUpstreamByAutomaticMode: common, test#1, test#2 + // - testChooseDunUpstreamByAutomaticMode_defaultNetworkWifi: test#3, test#4 + // - testChooseDunUpstreamByAutomaticMode_loseDefaultNetworkWifi: test#5 + // - testChooseDunUpstreamByAutomaticMode_defaultNetworkCell: test#5, test#7 + // - testChooseDunUpstreamByAutomaticMode_loseAndRegainDun: test#8 + // - testChooseDunUpstreamByAutomaticMode_switchDefaultFromWifiToCell: test#9, test#10 + // + // Overall test cases: + // +-------+-------+-------+-------+-------+ + // | Test | WiFi | Cellu | Dun | Expec | + // | Case | | alr | | ted | + // | # | | | | Upstr | + // | | | | | eam | + // +-------+-------+-------+-------+-------+ + // | - | | | | - | --+ + // +-------+-------+-------+-------+-------+ | + // | - | | V | | - | | + // +-------+-------+-------+-------+-------+ | + // | - | | V | O | Dun | +-- chooseDunUpstreamTestCommon + // +-------+-------+-------+-------+-------+ | + // | - | V | O | O | WiFi | | + // +-------+-------+-------+-------+-------+ | + // | - | V | O | | WiFi | --+ + // +-------+-------+-------+-------+-------+ + // | | O | V | | - | + // | 1 +-------+-------+-------+-------+ + // | | O | V | O | Dun | + // +-------+-------+-------+-------+-------+ + // | | O | V | | - | + // | 2 +-------+-------+-------+-------+ + // | | O | V | O | Dun | + // +-------+-------+-------+-------+-------+ + // | 3 | V | O | | WiFi | + // +-------+-------+-------+-------+-------+ + // | 4 | V | | | WiFi | + // +-------+-------+-------+-------+-------+ + // | 5 | | | O | Dun | + // +-------+-------+-------+-------+-------+ + // | 6 | | V | O | Dun | + // +-------+-------+-------+-------+-------+ + // | 7 | | | O | Dun | + // +-------+-------+-------+-------+-------+ + // | | | | | - | + // | 8 +-------+-------+-------+-------+ + // | | | | O | Dun | + // +-------+-------+-------+-------+-------+ + // | | V | | O | WiFi | + // | 9 +-------+-------+-------+-------+ + // | | V | | | WiFi | + // +-------+-------+-------+-------+-------+ + // | | O | V | | - | + // | 10 +-------+-------+-------+-------+ + // | | O | V | O | Dun | + // +-------+-------+-------+-------+-------+ + // + // Annotation: + // 1. "V" means that the given network is connected and it is default network. + // 2. "O" means that the given network is connected and it is not default network. + // + + // Test case: + // +-------+-------+-------+-------+-------+ + // | Test | WiFi | Cellu | Dun | Expec | + // | Case | | alr | | ted | + // | # | | | | Upstr | + // | | | | | eam | + // +-------+-------+-------+-------+-------+ + // | - | | | | - | --+ + // +-------+-------+-------+-------+-------+ | + // | - | | V | | - | | + // +-------+-------+-------+-------+-------+ | + // | - | | V | O | Dun | +-- chooseDunUpstreamTestCommon + // +-------+-------+-------+-------+-------+ | + // | - | V | O | O | WiFi | | + // +-------+-------+-------+-------+-------+ | + // | - | V | O | | WiFi | --+ + // +-------+-------+-------+-------+-------+ + // | | O | V | | - | + // | 1 +-------+-------+-------+-------+ + // | | O | V | O | Dun | + // +-------+-------+-------+-------+-------+ + // | | O | V | | - | + // | 2 +-------+-------+-------+-------+ + // | | O | V | O | Dun | + // +-------+-------+-------+-------+-------+ + // private void verifyChooseDunUpstreamByAutomaticMode(boolean configAutomatic) throws Exception { // Enable automatic upstream selection. TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState()); @@ -1345,20 +1473,14 @@ public class TetheringTest { InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor); chooseDunUpstreamTestCommon(configAutomatic, inOrder, mobile, wifi, dun); - // When default network switch to mobile and wifi is connected (may have low signal), + // [1] When default network switch to mobile and wifi is connected (may have low signal), // automatic mode would request dun again and choose it as upstream. mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST); mLooper.dispatchAll(); - inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true); - ArgumentCaptor captor = ArgumentCaptor.forClass(NetworkCallback.class); - inOrder.verify(mCm).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(), any()); - inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null); - final Runnable doDispatchAll = () -> mLooper.dispatchAll(); - dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll); - mLooper.dispatchAll(); - inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId); + verifyDunUpstream(inOrder, dun, true /* needToRequestNetwork */); - // Lose and regain upstream again. + // [2] Lose and regain upstream again. + final Runnable doDispatchAll = () -> mLooper.dispatchAll(); dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll); mLooper.dispatchAll(); inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true); @@ -1376,12 +1498,245 @@ public class TetheringTest { verifyChooseDunUpstreamByAutomaticMode(true /* configAutomatic */); } + // testChooseDunUpstreamByAutomaticMode_* doesn't verify configAutomatic:false because no + // matter |configAutomatic| set to true or false, the result always be automatic mode. We + // just need one test to make sure this behavior. Don't need to test this configuration + // in all tests. @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) public void testChooseDunUpstreamByAutomaticModeWithConfigDisabled() throws Exception { verifyChooseDunUpstreamByAutomaticMode(false /* configAutomatic */); } + // Test case: + // +-------+-------+-------+-------+-------+ + // | Test | WiFi | Cellu | Dun | Expec | + // | Case | | alr | | ted | + // | # | | | | Upstr | + // | | | | | eam | + // +-------+-------+-------+-------+-------+ + // | - | O | V | O | Dun | + // +-------+-------+-------+-------+-------+ + // | 3 | V | O | | WiFi | + // +-------+-------+-------+-------+-------+ + // | 4 | V | | | WiFi | + // +-------+-------+-------+-------+-------+ + // + // See verifyChooseDunUpstreamByAutomaticMode for the annotation. + // + @Test + public void testChooseDunUpstreamByAutomaticMode_defaultNetworkWifi() throws Exception { + TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState()); + TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState()); + TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState()); + final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor); + final NetworkCallback dunNetworkCallback1 = setupDunUpstreamTest( + true /* configAutomatic */, inOrder); + + // When wifi connected, unregister dun request and choose wifi as upstream. + wifi.fakeConnect(); + mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST); + mLooper.dispatchAll(); + verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback1); + + // When default network switch to mobile and wifi is connected (may have low signal), + // automatic mode would request dun again and choose it as upstream. + mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST); + mLooper.dispatchAll(); + final NetworkCallback dunNetworkCallback2 = + verifyDunUpstream(inOrder, dun, true /* needToRequestNetwork */); + + // [3] When default network switch to wifi and mobile is still connected, + // unregister dun request and choose wifi as upstream. + mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST); + mLooper.dispatchAll(); + verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback2); + + // [4] When mobile is disconnected, keep wifi as upstream. + final Runnable doDispatchAll = () -> mLooper.dispatchAll(); + mobile.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll); + mLooper.dispatchAll(); + inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any()); + + verifyDisableTryCellWhenTetheringStop(inOrder); + } + + // Test case: + // +-------+-------+-------+-------+-------+ + // | Test | WiFi | Cellu | Dun | Expec | + // | Case | | alr | | ted | + // | # | | | | Upstr | + // | | | | | eam | + // +-------+-------+-------+-------+-------+ + // | - | V | | | WiFi | + // +-------+-------+-------+-------+-------+ + // | 5 | | | O | Dun | + // +-------+-------+-------+-------+-------+ + // + // See verifyChooseDunUpstreamByAutomaticMode for the annotation. + // + @Test + public void testChooseDunUpstreamByAutomaticMode_loseDefaultNetworkWifi() throws Exception { + TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState()); + TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState()); + final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor); + final NetworkCallback dunNetworkCallback = setupDunUpstreamTest( + true /* configAutomatic */, inOrder); + + // When wifi connected, unregister dun request and choose wifi as upstream. + wifi.fakeConnect(); + mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST); + mLooper.dispatchAll(); + verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback); + + // [5] When wifi is disconnected, automatic mode would request dun again and choose it + // as upstream. + final Runnable doDispatchAll = () -> mLooper.dispatchAll(); + mCm.makeDefaultNetwork(null, CALLBACKS_FIRST, doDispatchAll); + wifi.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll); + mLooper.dispatchAll(); + verifyDunUpstream(inOrder, dun, true /* needToRequestNetwork */); + + verifyDisableTryCellWhenTetheringStop(inOrder); + } + + // Test case: + // +-------+-------+-------+-------+-------+ + // | Test | WiFi | Cellu | Dun | Expec | + // | Case | | alr | | ted | + // | # | | | | Upstr | + // | | | | | eam | + // +-------+-------+-------+-------+-------+ + // | - | | | O | Dun | + // +-------+-------+-------+-------+-------+ + // | 6 | | V | O | Dun | + // +-------+-------+-------+-------+-------+ + // | 7 | | | O | Dun | + // +-------+-------+-------+-------+-------+ + // + // See verifyChooseDunUpstreamByAutomaticMode for the annotation. + // + @Test + public void testChooseDunUpstreamByAutomaticMode_defaultNetworkCell() throws Exception { + TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState()); + TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState()); + final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor); + setupDunUpstreamTest(true /* configAutomatic */, inOrder); + + // Pretend dun connected and expect choose dun as upstream. + final Runnable doDispatchAll = () -> mLooper.dispatchAll(); + dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll); + mLooper.dispatchAll(); + inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId); + + // [6] When mobile is connected and default network switch to mobile, keep dun as upstream. + mobile.fakeConnect(); + mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST); + mLooper.dispatchAll(); + inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any()); + + // [7] When mobile is disconnected, keep dun as upstream. + mCm.makeDefaultNetwork(null, CALLBACKS_FIRST, doDispatchAll); + mobile.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll); + mLooper.dispatchAll(); + inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any()); + + verifyDisableTryCellWhenTetheringStop(inOrder); + } + + // Test case: + // +-------+-------+-------+-------+-------+ + // | Test | WiFi | Cellu | Dun | Expec | + // | Case | | alr | | ted | + // | # | | | | Upstr | + // | | | | | eam | + // +-------+-------+-------+-------+-------+ + // | - | | | O | Dun | + // +-------+-------+-------+-------+-------+ + // | | | | | - | + // | 8 +-------+-------+-------+-------+ + // | | | | O | Dun | + // +-------+-------+-------+-------+-------+ + // + // See verifyChooseDunUpstreamByAutomaticMode for the annotation. + // + @Test + public void testChooseDunUpstreamByAutomaticMode_loseAndRegainDun() throws Exception { + TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState()); + final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor); + setupDunUpstreamTest(true /* configAutomatic */, inOrder); + + // Pretend dun connected and expect choose dun as upstream. + final Runnable doDispatchAll = () -> mLooper.dispatchAll(); + dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll); + mLooper.dispatchAll(); + inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId); + + // [8] Lose and regain upstream again. + dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll); + mLooper.dispatchAll(); + verifyDunUpstream(inOrder, dun, false /* needToRequestNetwork */); + + verifyDisableTryCellWhenTetheringStop(inOrder); + } + + // Test case: + // +-------+-------+-------+-------+-------+ + // | Test | WiFi | Cellu | Dun | Expec | + // | Case | | alr | | ted | + // | # | | | | Upstr | + // | | | | | eam | + // +-------+-------+-------+-------+-------+ + // | - | | | O | Dun | + // +-------+-------+-------+-------+-------+ + // | | V | | O | WiFi | + // | 9 +-------+-------+-------+-------+ + // | | V | | | WiFi | + // +-------+-------+-------+-------+-------+ + // | | O | V | | - | + // | 10 +-------+-------+-------+-------+ + // | | O | V | O | Dun | + // +-------+-------+-------+-------+-------+ + // + // See verifyChooseDunUpstreamByAutomaticMode for the annotation. + // + @Test + public void testChooseDunUpstreamByAutomaticMode_switchDefaultFromWifiToCell() + throws Exception { + TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState()); + TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState()); + TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState()); + final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor); + final NetworkCallback dunNetworkCallback = setupDunUpstreamTest( + true /* configAutomatic */, inOrder); + + // Pretend dun connected and expect choose dun as upstream. + final Runnable doDispatchAll = () -> mLooper.dispatchAll(); + dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll); + mLooper.dispatchAll(); + inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId); + + // [9] When wifi is connected and default network switch to wifi, unregister dun request + // and choose wifi as upstream. When dun is disconnected, keep wifi as upstream. + wifi.fakeConnect(); + mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST); + mLooper.dispatchAll(); + verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback); + dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll); + mLooper.dispatchAll(); + inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any()); + + // [10] When mobile and mobile are connected and default network switch to mobile + // (may have low signal), automatic mode would request dun again and choose it as + // upstream. + mobile.fakeConnect(); + mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST); + mLooper.dispatchAll(); + verifyDunUpstream(inOrder, dun, true /* needToRequestNetwork */); + + verifyDisableTryCellWhenTetheringStop(inOrder); + } + @Test @IgnoreAfter(Build.VERSION_CODES.TIRAMISU) public void testChooseDunUpstreamByLegacyMode() throws Exception { @@ -1445,7 +1800,7 @@ public class TetheringTest { private void chooseDunUpstreamTestCommon(final boolean automatic, InOrder inOrder, TestNetworkAgent mobile, TestNetworkAgent wifi, TestNetworkAgent dun) throws Exception { - final NetworkCallback dunNetworkCallback1 = setupDunUpstreamTest(automatic, inOrder); + final NetworkCallback dunNetworkCallback = setupDunUpstreamTest(automatic, inOrder); // Pretend cellular connected and expect the upstream to be set. mobile.fakeConnect(); @@ -1463,9 +1818,7 @@ public class TetheringTest { wifi.fakeConnect(); mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST); mLooper.dispatchAll(); - inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false); - inOrder.verify(mCm).unregisterNetworkCallback(eq(dunNetworkCallback1)); - inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId); + verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback); dun.fakeDisconnect(BROADCAST_FIRST, doDispatchAll); mLooper.dispatchAll(); inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any()); From a432d621b0fba05a4d5cb93083173125980d276f Mon Sep 17 00:00:00 2001 From: Hungming Chen Date: Fri, 4 Nov 2022 18:04:02 +0800 Subject: [PATCH 3/3] Tethering: deprecate CONNECTIVITY_ACTION on U+ device Both CONNECTIVITY_ACTION and UpstreamNetworkMonitor monitor the upstream connection status. The upstream status should be monitored in one place and deprecated the duplicate one since U+ device. Once CONNECTIVITY_ACTION is removed, CMD_UPSTREAM_CHANGED won't be triggered anymore. For non-dun upstream netowrk , upstream re-evaluation is triggered by EVENT_DEFAULT_SWITCHED and EVENT_ON_LOST. For dun upstream re-evaluation, re-evaluation is triggered by EVENT_ON_LINKPROPERTIES and EVENT_ON_LOST. Changes: 1. Deprecate the CONNECTIVITY_ACTION broadcast. 2. Re-evaluate possible upstream selection on the event UpstreamNetworkMonitor.EVENT_ON_LOST. Note that EVENT_DEFAULT_SWITCHED and EVENT_ON_LINKPROPERTIES have already triggered the upstream re-evaluation and keep as it. Bug: 257408654 Bug: 257941865 Test: atest ConnectivityCoverageTests Change-Id: I8b75cfb2fec51fb5bc4e2d13ad6b54daf8efc71e --- .../src/com/android/networkstack/tethering/Tethering.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java index f0dd030f33..06e665cb8f 100644 --- a/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -1195,6 +1195,9 @@ public class Tethering { } private void handleConnectivityAction(Intent intent) { + // CONNECTIVITY_ACTION is not handled since U+ device. + if (SdkLevel.isAtLeastU()) return; + final NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO); if (networkInfo == null @@ -2026,6 +2029,11 @@ public class Tethering { // broadcasts that result in being passed a // TetherMainSM.CMD_UPSTREAM_CHANGED. handleNewUpstreamNetworkState(null); + + if (SdkLevel.isAtLeastU()) { + // Need to try DUN immediately if Wi-Fi goes down. + chooseUpstreamType(true); + } break; default: mLog.e("Unknown arg1 value: " + arg1);