Merge changes from topic "deprecate_connectivity_action_in_tethering"

* changes:
  Tethering: deprecate CONNECTIVITY_ACTION on U+ device
  Test: add tests to testChooseDunUpstreamByAutomaticMode_*
  TetheringTest: separate setup func from chooseDunUpstreamTestCommon
This commit is contained in:
Treehugger Robot 2023-01-13 08:41:20 +00:00 • committed by Gerrit Code Review
commit 401f1ff2db
2 changed files with 383 additions and 17 deletions

View file

@ -1203,6 +1203,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
@ -2034,6 +2037,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);

View file

@ -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<NetworkCallback> 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<NetworkCallback> 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 {
@ -1425,8 +1780,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 +1793,14 @@ public class TetheringTest {
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
ArgumentCaptor<NetworkCallback> 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 dunNetworkCallback = setupDunUpstreamTest(automatic, inOrder);
// Pretend cellular connected and expect the upstream to be set.
mobile.fakeConnect();
@ -1458,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());