Add a method to create a TAP interface without bringing it up.

In S, the behaviour of createTunInterface and createTapInterface
changed so that they bring up the interface before returning it.
This makes it difficult to test code that brings interfaces up
itself, such as IpClient or EthernetManager, because the tests
cannot predict whether that code will see the interface up
or not. This leads to flaky tests and can even make it impossible
to reliably test some behaviour.

Add a method that allows the caller to specify whether to bring
up the interface or not.

Test: new codepath tested by other CL in topic
Test: existing codepaths already well-covered
Change-Id: I0f7698f4dad132f201db4203e65a78c6af564ab2
This commit is contained in:
Lorenzo Colitti
2022-02-14 09:05:27 +09:00
committed by Xiao Ma
parent 1c2f79705f
commit 333d5e52f5
3 changed files with 33 additions and 29 deletions

View File

@@ -29,8 +29,7 @@ import android.os.ParcelFileDescriptor;
*/ */
interface ITestNetworkManager interface ITestNetworkManager
{ {
TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs); TestNetworkInterface createInterface(boolean isTun, boolean bringUp, in LinkAddress[] addrs);
TestNetworkInterface createTapInterface();
void setupTestNetwork(in String iface, in LinkProperties lp, in boolean isMetered, void setupTestNetwork(in String iface, in LinkProperties lp, in boolean isMetered,
in int[] administratorUids, in IBinder binder); in int[] administratorUids, in IBinder binder);

View File

@@ -49,6 +49,11 @@ public class TestNetworkManager {
@NonNull private final ITestNetworkManager mService; @NonNull private final ITestNetworkManager mService;
private static final boolean TAP = false;
private static final boolean TUN = true;
private static final boolean BRING_UP = true;
private static final LinkAddress[] NO_ADDRS = new LinkAddress[0];
/** @hide */ /** @hide */
public TestNetworkManager(@NonNull ITestNetworkManager service) { public TestNetworkManager(@NonNull ITestNetworkManager service) {
mService = Objects.requireNonNull(service, "missing ITestNetworkManager"); mService = Objects.requireNonNull(service, "missing ITestNetworkManager");
@@ -155,7 +160,7 @@ public class TestNetworkManager {
public TestNetworkInterface createTunInterface(@NonNull Collection<LinkAddress> linkAddrs) { public TestNetworkInterface createTunInterface(@NonNull Collection<LinkAddress> linkAddrs) {
try { try {
final LinkAddress[] arr = new LinkAddress[linkAddrs.size()]; final LinkAddress[] arr = new LinkAddress[linkAddrs.size()];
return mService.createTunInterface(linkAddrs.toArray(arr)); return mService.createInterface(TUN, BRING_UP, linkAddrs.toArray(arr));
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -173,10 +178,28 @@ public class TestNetworkManager {
@NonNull @NonNull
public TestNetworkInterface createTapInterface() { public TestNetworkInterface createTapInterface() {
try { try {
return mService.createTapInterface(); return mService.createInterface(TAP, BRING_UP, NO_ADDRS);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
} }
/**
* Create a tap interface for testing purposes
*
* @param bringUp whether to bring up the interface before returning it.
*
* @return A ParcelFileDescriptor of the underlying TAP interface. Close this to tear down the
* TAP interface.
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
@NonNull
public TestNetworkInterface createTapInterface(boolean bringUp) {
try {
return mService.createInterface(TAP, bringUp, NO_ADDRS);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
} }

View File

@@ -99,12 +99,14 @@ class TestNetworkService extends ITestNetworkManager.Stub {
} }
/** /**
* Create a TUN or TAP interface with the given interface name and link addresses * Create a TUN or TAP interface with the specified parameters.
* *
* <p>This method will return the FileDescriptor to the interface. Close it to tear down the * <p>This method will return the FileDescriptor to the interface. Close it to tear down the
* interface. * interface.
*/ */
private TestNetworkInterface createInterface(boolean isTun, LinkAddress[] linkAddrs) { @Override
public TestNetworkInterface createInterface(boolean isTun, boolean bringUp,
LinkAddress[] linkAddrs) {
enforceTestNetworkPermissions(mContext); enforceTestNetworkPermissions(mContext);
Objects.requireNonNull(linkAddrs, "missing linkAddrs"); Objects.requireNonNull(linkAddrs, "missing linkAddrs");
@@ -122,7 +124,9 @@ class TestNetworkService extends ITestNetworkManager.Stub {
addr.getPrefixLength()); addr.getPrefixLength());
} }
NetdUtils.setInterfaceUp(mNetd, iface); if (bringUp) {
NetdUtils.setInterfaceUp(mNetd, iface);
}
return new TestNetworkInterface(tunIntf, iface); return new TestNetworkInterface(tunIntf, iface);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -132,28 +136,6 @@ class TestNetworkService extends ITestNetworkManager.Stub {
} }
} }
/**
* Create a TUN interface with the given interface name and link addresses
*
* <p>This method will return the FileDescriptor to the TUN interface. Close it to tear down the
* TUN interface.
*/
@Override
public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
return createInterface(true, linkAddrs);
}
/**
* Create a TAP interface with the given interface name
*
* <p>This method will return the FileDescriptor to the TAP interface. Close it to tear down the
* TAP interface.
*/
@Override
public TestNetworkInterface createTapInterface() {
return createInterface(false, new LinkAddress[0]);
}
// Tracker for TestNetworkAgents // Tracker for TestNetworkAgents
@GuardedBy("mTestNetworkTracker") @GuardedBy("mTestNetworkTracker")
@NonNull @NonNull