Merge "EthernetTetheringTest: toggle wifi while test network is not selected"

This commit is contained in:
Treehugger Robot
2022-09-14 14:25:13 +00:00
committed by Gerrit Code Review
3 changed files with 74 additions and 5 deletions

View File

@@ -21,6 +21,7 @@ import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.TETHER_PRIVILEGED;
import static android.content.pm.PackageManager.FEATURE_WIFI;
import static android.net.InetAddresses.parseNumericAddress;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
@@ -55,12 +56,14 @@ import static org.junit.Assume.assumeTrue;
import android.app.UiAutomation;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.EthernetManager.TetheredInterfaceCallback;
import android.net.EthernetManager.TetheredInterfaceRequest;
import android.net.TetheringManager.StartTetheringCallback;
import android.net.TetheringManager.TetheringEventCallback;
import android.net.TetheringManager.TetheringRequest;
import android.net.TetheringTester.TetheredDevice;
import android.net.cts.util.CtsNetUtils;;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
@@ -239,6 +242,8 @@ public class EthernetTetheringTest {
private final Context mContext = InstrumentationRegistry.getContext();
private final EthernetManager mEm = mContext.getSystemService(EthernetManager.class);
private final TetheringManager mTm = mContext.getSystemService(TetheringManager.class);
private final PackageManager mPackageManager = mContext.getPackageManager();
private final CtsNetUtils mCtsNetUtils = new CtsNetUtils(mContext);
private TestNetworkInterface mDownstreamIface;
private HandlerThread mHandlerThread;
@@ -702,10 +707,17 @@ public class EthernetTetheringTest {
}
}
public Network awaitUpstreamChanged() throws Exception {
public Network awaitUpstreamChanged(boolean throwTimeoutException) throws Exception {
if (!mUpstreamLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
fail("Did not receive upstream " + (mAcceptAnyUpstream ? "any" : mExpectedUpstream)
+ " callback after " + TIMEOUT_MS + "ms");
final String errorMessage = "Did not receive upstream "
+ (mAcceptAnyUpstream ? "any" : mExpectedUpstream)
+ " callback after " + TIMEOUT_MS + "ms";
if (throwTimeoutException) {
throw new TimeoutException(errorMessage);
} else {
fail(errorMessage);
}
}
return mUpstream;
}
@@ -1247,6 +1259,52 @@ public class EthernetTetheringTest {
}
}
// TODO: remove triggering upstream reselection once test network can replace selected upstream
// network in Tethering module.
private void maybeRetryTestedUpstreamChanged(final Network expectedUpstream,
final TimeoutException fallbackException) throws Exception {
// Fall back original exception because no way to reselect if there is no WIFI feature.
assertTrue(fallbackException.toString(), mPackageManager.hasSystemFeature(FEATURE_WIFI));
// Try to toggle wifi network, if any, to reselect upstream network via default network
// switching. Because test network has higher priority than internet network, this can
// help selecting test network to be upstream network for testing. This tries to avoid
// the flaky upstream selection under multinetwork environment. Internet and test network
// upstream changed event order is not guaranteed. Once tethering selects non-test
// upstream {wifi, ..}, test network won't be selected anymore. If too many test cases
// trigger the reselection, the total test time may over test suite 1 minmute timeout.
// Probably need to disable/restore all internet networks in a common place of test
// process. Currently, EthernetTetheringTest is part of CTS test which needs wifi network
// connection if device has wifi feature. CtsNetUtils#toggleWifi() checks wifi connection
// during the toggling process.
// See Tethering#chooseUpstreamType, CtsNetUtils#toggleWifi.
// TODO: toggle cellular network if the device has no WIFI feature.
Log.d(TAG, "Toggle WIFI to retry upstream selection");
mCtsNetUtils.toggleWifi();
// Wait for expected upstream.
final CompletableFuture<Network> future = new CompletableFuture<>();
final TetheringEventCallback callback = new TetheringEventCallback() {
@Override
public void onUpstreamChanged(Network network) {
Log.d(TAG, "Got upstream changed: " + network);
if (Objects.equals(expectedUpstream, network)) {
future.complete(network);
}
}
};
try {
mTm.registerTetheringEventCallback(mHandler::post, callback);
assertEquals("onUpstreamChanged for unexpected network", expectedUpstream,
future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} catch (TimeoutException e) {
throw new AssertionError("Did not receive upstream " + expectedUpstream
+ " callback after " + TIMEOUT_MS + "ms");
} finally {
mTm.unregisterTetheringEventCallback(callback);
}
}
private TetheringTester initTetheringTester(List<LinkAddress> upstreamAddresses,
List<InetAddress> upstreamDnses) throws Exception {
assumeFalse(isInterfaceForTetheringAvailable());
@@ -1265,8 +1323,17 @@ public class EthernetTetheringTest {
mTetheringEventCallback = enableEthernetTethering(mDownstreamIface.getInterfaceName(),
mUpstreamTracker.getNetwork());
assertEquals("onUpstreamChanged for unexpected network", mUpstreamTracker.getNetwork(),
mTetheringEventCallback.awaitUpstreamChanged());
try {
assertEquals("onUpstreamChanged for test network", mUpstreamTracker.getNetwork(),
mTetheringEventCallback.awaitUpstreamChanged(
true /* throwTimeoutException */));
} catch (TimeoutException e) {
// Due to race condition inside tethering module, test network may not be selected as
// tethering upstream. Force tethering retry upstream if possible. If it is not
// possible to retry, fail the test with the original timeout exception.
maybeRetryTestedUpstreamChanged(mUpstreamTracker.getNetwork(), e);
}
mDownstreamReader = makePacketReader(mDownstreamIface);
mUpstreamReader = makePacketReader(mUpstreamTracker.getTestIface());