[Tether09] Use INetd to call netd directly

- Using INetd to communicate with netd directly instead of using
NetworkManagementService which is a wrapper of INetd and don't have plan
to be updatable.
- Also replace InterfaceConfiguration by InterfaceController.
- Remove redundant interface flags. Only set interface up/down flag to
netd because netd only use these two flags for INetd#interfaceSetCfg.
- Note that tethering still use NetworkManagementService
to register tethering stats provider and it would also be replaced with
other way in follow up change.

Bug: 136040414
Test: -build, flash, boot
      -atest TetheringTests

Change-Id: I4ab0ad387d4bd1773ff94d3b380c1720df07f8d5
This commit is contained in:
markchien
2020-01-07 14:43:17 +08:00
parent 0b4fd06744
commit dac2826929
5 changed files with 341 additions and 328 deletions

View File

@@ -20,7 +20,7 @@ java_defaults {
srcs: [ srcs: [
"src/**/*.java", "src/**/*.java",
":framework-tethering-shared-srcs", ":framework-tethering-shared-srcs",
":net-module-utils-srcs", ":tethering-module-utils-srcs",
":services-tethering-shared-srcs", ":services-tethering-shared-srcs",
], ],
static_libs: [ static_libs: [

View File

@@ -28,7 +28,6 @@ import android.net.ConnectivityManager;
import android.net.INetd; import android.net.INetd;
import android.net.INetworkStackStatusCallback; import android.net.INetworkStackStatusCallback;
import android.net.INetworkStatsService; import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix; import android.net.IpPrefix;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
@@ -38,11 +37,11 @@ import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.DhcpServingParamsParcelExt; import android.net.dhcp.DhcpServingParamsParcelExt;
import android.net.dhcp.IDhcpServer; import android.net.dhcp.IDhcpServer;
import android.net.ip.RouterAdvertisementDaemon.RaParams; import android.net.ip.RouterAdvertisementDaemon.RaParams;
import android.net.shared.NetdUtils;
import android.net.shared.RouteUtils;
import android.net.util.InterfaceParams; import android.net.util.InterfaceParams;
import android.net.util.InterfaceSet; import android.net.util.InterfaceSet;
import android.net.util.NetdService;
import android.net.util.SharedLog; import android.net.util.SharedLog;
import android.os.INetworkManagementService;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.RemoteException; import android.os.RemoteException;
@@ -144,10 +143,6 @@ public class IpServer extends StateMachine {
return InterfaceParams.getByName(ifName); return InterfaceParams.getByName(ifName);
} }
public INetd getNetdService() {
return NetdService.getInstance();
}
/** Create a DhcpServer instance to be used by IpServer. */ /** Create a DhcpServer instance to be used by IpServer. */
public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params, public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
DhcpServerCallbacks cb); DhcpServerCallbacks cb);
@@ -180,7 +175,6 @@ public class IpServer extends StateMachine {
private final State mUnavailableState; private final State mUnavailableState;
private final SharedLog mLog; private final SharedLog mLog;
private final INetworkManagementService mNMService;
private final INetd mNetd; private final INetd mNetd;
private final INetworkStatsService mStatsService; private final INetworkStatsService mStatsService;
private final Callback mCallback; private final Callback mCallback;
@@ -210,15 +204,15 @@ public class IpServer extends StateMachine {
private int mDhcpServerStartIndex = 0; private int mDhcpServerStartIndex = 0;
private IDhcpServer mDhcpServer; private IDhcpServer mDhcpServer;
private RaParams mLastRaParams; private RaParams mLastRaParams;
private LinkAddress mIpv4Address;
public IpServer( public IpServer(
String ifaceName, Looper looper, int interfaceType, SharedLog log, String ifaceName, Looper looper, int interfaceType, SharedLog log,
INetworkManagementService nMService, INetworkStatsService statsService, INetd netd, INetworkStatsService statsService, Callback callback,
Callback callback, boolean usingLegacyDhcp, Dependencies deps) { boolean usingLegacyDhcp, Dependencies deps) {
super(ifaceName, looper); super(ifaceName, looper);
mLog = log.forSubComponent(ifaceName); mLog = log.forSubComponent(ifaceName);
mNMService = nMService; mNetd = netd;
mNetd = deps.getNetdService();
mStatsService = statsService; mStatsService = statsService;
mCallback = callback; mCallback = callback;
mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog); mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog);
@@ -347,7 +341,7 @@ public class IpServer extends StateMachine {
} }
}); });
} catch (RemoteException e) { } catch (RemoteException e) {
e.rethrowFromSystemServer(); throw new IllegalStateException(e);
} }
}); });
} }
@@ -395,7 +389,8 @@ public class IpServer extends StateMachine {
}); });
mDhcpServer = null; mDhcpServer = null;
} catch (RemoteException e) { } catch (RemoteException e) {
e.rethrowFromSystemServer(); mLog.e("Error stopping DHCP", e);
// Not much more we can do here
} }
} }
} }
@@ -414,85 +409,69 @@ public class IpServer extends StateMachine {
// NOTE: All of configureIPv4() will be refactored out of existence // NOTE: All of configureIPv4() will be refactored out of existence
// into calls to InterfaceController, shared with startIPv4(). // into calls to InterfaceController, shared with startIPv4().
mInterfaceCtrl.clearIPv4Address(); mInterfaceCtrl.clearIPv4Address();
mIpv4Address = null;
} }
// TODO: Refactor this in terms of calls to InterfaceController.
private boolean configureIPv4(boolean enabled) { private boolean configureIPv4(boolean enabled) {
if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")"); if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
// TODO: Replace this hard-coded information with dynamically selected // TODO: Replace this hard-coded information with dynamically selected
// config passed down to us by a higher layer IP-coordinating element. // config passed down to us by a higher layer IP-coordinating element.
String ipAsString = null; final Inet4Address srvAddr;
int prefixLen = 0; int prefixLen = 0;
try {
if (mInterfaceType == ConnectivityManager.TETHERING_USB) { if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
ipAsString = USB_NEAR_IFACE_ADDR; srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR);
prefixLen = USB_PREFIX_LENGTH; prefixLen = USB_PREFIX_LENGTH;
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
ipAsString = getRandomWifiIPv4Address(); srvAddr = (Inet4Address) parseNumericAddress(getRandomWifiIPv4Address());
prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH; prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) { } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) {
ipAsString = WIFI_P2P_IFACE_ADDR; srvAddr = (Inet4Address) parseNumericAddress(WIFI_P2P_IFACE_ADDR);
prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH; prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
} else { } else {
// BT configures the interface elsewhere: only start DHCP. // BT configures the interface elsewhere: only start DHCP.
final Inet4Address srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR); // TODO: make all tethering types behave the same way, and delete the bluetooth
// code that calls into NetworkManagementService directly.
srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH); return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
} }
mIpv4Address = new LinkAddress(srvAddr, prefixLen);
final LinkAddress linkAddr; } catch (IllegalArgumentException e) {
try { mLog.e("Error selecting ipv4 address", e);
final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName); if (!enabled) stopDhcp();
if (ifcg == null) {
mLog.e("Received null interface config");
return false; return false;
} }
InetAddress addr = parseNumericAddress(ipAsString); final Boolean setIfaceUp;
linkAddr = new LinkAddress(addr, prefixLen);
ifcg.setLinkAddress(linkAddr);
if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
// The WiFi stack has ownership of the interface up/down state. // The WiFi stack has ownership of the interface up/down state.
// It is unclear whether the Bluetooth or USB stacks will manage their own // It is unclear whether the Bluetooth or USB stacks will manage their own
// state. // state.
ifcg.ignoreInterfaceUpDownStatus(); setIfaceUp = null;
} else { } else {
if (enabled) { setIfaceUp = enabled;
ifcg.setInterfaceUp();
} else {
ifcg.setInterfaceDown();
} }
} if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) {
ifcg.clearFlag("running"); mLog.e("Error configuring interface");
if (!enabled) stopDhcp();
// TODO: this may throw if the interface is already gone. Do proper handling and
// simplify the DHCP server start/stop.
mNMService.setInterfaceConfig(mIfaceName, ifcg);
if (!configureDhcp(enabled, (Inet4Address) addr, prefixLen)) {
return false; return false;
} }
} catch (Exception e) {
mLog.e("Error configuring interface " + e); if (!configureDhcp(enabled, srvAddr, prefixLen)) {
if (!enabled) {
try {
// Calling stopDhcp several times is fine
stopDhcp();
} catch (Exception dhcpError) {
mLog.e("Error stopping DHCP", dhcpError);
}
}
return false; return false;
} }
// Directly-connected route. // Directly-connected route.
final IpPrefix ipv4Prefix = new IpPrefix(linkAddr.getAddress(), final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
linkAddr.getPrefixLength()); mIpv4Address.getPrefixLength());
final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST); final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST);
if (enabled) { if (enabled) {
mLinkProperties.addLinkAddress(linkAddr); mLinkProperties.addLinkAddress(mIpv4Address);
mLinkProperties.addRoute(route); mLinkProperties.addRoute(route);
} else { } else {
mLinkProperties.removeLinkAddress(linkAddr); mLinkProperties.removeLinkAddress(mIpv4Address);
mLinkProperties.removeRoute(route); mLinkProperties.removeRoute(route);
} }
return true; return true;
@@ -584,15 +563,13 @@ public class IpServer extends StateMachine {
if (!deprecatedPrefixes.isEmpty()) { if (!deprecatedPrefixes.isEmpty()) {
final ArrayList<RouteInfo> toBeRemoved = final ArrayList<RouteInfo> toBeRemoved =
getLocalRoutesFor(mIfaceName, deprecatedPrefixes); getLocalRoutesFor(mIfaceName, deprecatedPrefixes);
try { // Remove routes from local network.
final int removalFailures = mNMService.removeRoutesFromLocalNetwork(toBeRemoved); final int removalFailures = RouteUtils.removeRoutesFromLocalNetwork(
mNetd, toBeRemoved);
if (removalFailures > 0) { if (removalFailures > 0) {
mLog.e(String.format("Failed to remove %d IPv6 routes from local table.", mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
removalFailures)); removalFailures));
} }
} catch (RemoteException e) {
mLog.e("Failed to remove IPv6 routes from local table: " + e);
}
for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route); for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route);
} }
@@ -608,14 +585,19 @@ public class IpServer extends StateMachine {
final ArrayList<RouteInfo> toBeAdded = final ArrayList<RouteInfo> toBeAdded =
getLocalRoutesFor(mIfaceName, addedPrefixes); getLocalRoutesFor(mIfaceName, addedPrefixes);
try { try {
// It's safe to call addInterfaceToLocalNetwork() even if // It's safe to call networkAddInterface() even if
// the interface is already in the local_network. Note also // the interface is already in the local_network.
// that adding routes that already exist does not cause an mNetd.networkAddInterface(INetd.LOCAL_NET_ID, mIfaceName);
// error (EEXIST is silently ignored). try {
mNMService.addInterfaceToLocalNetwork(mIfaceName, toBeAdded); // Add routes from local network. Note that adding routes that
} catch (Exception e) { // already exist does not cause an error (EEXIST is silently ignored).
RouteUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded);
} catch (IllegalStateException e) {
mLog.e("Failed to add IPv6 routes to local table: " + e); mLog.e("Failed to add IPv6 routes to local table: " + e);
} }
} catch (ServiceSpecificException | RemoteException e) {
mLog.e("Failed to add " + mIfaceName + " to local table: ", e);
}
for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route); for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route);
} }
@@ -762,8 +744,10 @@ public class IpServer extends StateMachine {
} }
try { try {
mNMService.tetherInterface(mIfaceName); final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
} catch (Exception e) { mIpv4Address.getPrefixLength());
NetdUtils.tetherInterface(mNetd, mIfaceName, ipv4Prefix);
} catch (RemoteException | ServiceSpecificException e) {
mLog.e("Error Tethering: " + e); mLog.e("Error Tethering: " + e);
mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR; mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
return; return;
@@ -784,8 +768,8 @@ public class IpServer extends StateMachine {
stopIPv6(); stopIPv6();
try { try {
mNMService.untetherInterface(mIfaceName); NetdUtils.untetherInterface(mNetd, mIfaceName);
} catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) {
mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
mLog.e("Failed to untether interface: " + e); mLog.e("Failed to untether interface: " + e);
} }
@@ -901,17 +885,17 @@ public class IpServer extends StateMachine {
// About to tear down NAT; gather remaining statistics. // About to tear down NAT; gather remaining statistics.
mStatsService.forceUpdate(); mStatsService.forceUpdate();
} catch (Exception e) { } catch (Exception e) {
if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString()); mLog.e("Exception in forceUpdate: " + e.toString());
} }
try { try {
mNMService.stopInterfaceForwarding(mIfaceName, upstreamIface); mNetd.ipfwdRemoveInterfaceForward(mIfaceName, upstreamIface);
} catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) {
if (VDBG) Log.e(TAG, "Exception in removeInterfaceForward: " + e.toString()); mLog.e("Exception in ipfwdRemoveInterfaceForward: " + e.toString());
} }
try { try {
mNMService.disableNat(mIfaceName, upstreamIface); mNetd.tetherRemoveForward(mIfaceName, upstreamIface);
} catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) {
if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString()); mLog.e("Exception in disableNat: " + e.toString());
} }
} }
@@ -947,10 +931,10 @@ public class IpServer extends StateMachine {
for (String ifname : added) { for (String ifname : added) {
try { try {
mNMService.enableNat(mIfaceName, ifname); mNetd.tetherAddForward(mIfaceName, ifname);
mNMService.startInterfaceForwarding(mIfaceName, ifname); mNetd.ipfwdAddInterfaceForward(mIfaceName, ifname);
} catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) {
mLog.e("Exception enabling NAT: " + e); mLog.e("Exception enabling NAT: " + e.toString());
cleanupUpstream(); cleanupUpstream();
mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR; mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
transitionTo(mInitialState); transitionTo(mInitialState);

View File

@@ -75,6 +75,7 @@ import android.net.NetworkUtils;
import android.net.TetherStatesParcel; import android.net.TetherStatesParcel;
import android.net.TetheringConfigurationParcel; import android.net.TetheringConfigurationParcel;
import android.net.ip.IpServer; import android.net.ip.IpServer;
import android.net.shared.NetdUtils;
import android.net.util.BaseNetdUnsolicitedEventListener; import android.net.util.BaseNetdUnsolicitedEventListener;
import android.net.util.InterfaceSet; import android.net.util.InterfaceSet;
import android.net.util.PrefixUtils; import android.net.util.PrefixUtils;
@@ -87,12 +88,12 @@ import android.net.wifi.p2p.WifiP2pManager;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.RemoteCallbackList; import android.os.RemoteCallbackList;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.os.ServiceSpecificException;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.telephony.PhoneStateListener; import android.telephony.PhoneStateListener;
@@ -102,6 +103,9 @@ import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.notification.SystemNotificationChannels;
@@ -139,6 +143,8 @@ public class Tethering {
}; };
private static final SparseArray<String> sMagicDecoderRing = private static final SparseArray<String> sMagicDecoderRing =
MessageUtils.findMessageNames(sMessageClasses); MessageUtils.findMessageNames(sMessageClasses);
// Keep in sync with NETID_UNSET in system/netd/include/netid_client.h
private static final int NETID_UNSET = 0;
private static class TetherState { private static class TetherState {
public final IpServer ipServer; public final IpServer ipServer;
@@ -172,8 +178,6 @@ public class Tethering {
private final Context mContext; private final Context mContext;
private final ArrayMap<String, TetherState> mTetherStates; private final ArrayMap<String, TetherState> mTetherStates;
private final BroadcastReceiver mStateReceiver; private final BroadcastReceiver mStateReceiver;
// Stopship: replace mNMService before production.
private final INetworkManagementService mNMService;
private final INetworkStatsService mStatsService; private final INetworkStatsService mStatsService;
private final INetworkPolicyManager mPolicyManager; private final INetworkPolicyManager mPolicyManager;
private final Looper mLooper; private final Looper mLooper;
@@ -210,7 +214,6 @@ public class Tethering {
mLog.mark("Tethering.constructed"); mLog.mark("Tethering.constructed");
mDeps = deps; mDeps = deps;
mContext = mDeps.getContext(); mContext = mDeps.getContext();
mNMService = mDeps.getINetworkManagementService();
mStatsService = mDeps.getINetworkStatsService(); mStatsService = mDeps.getINetworkStatsService();
mPolicyManager = mDeps.getINetworkPolicyManager(); mPolicyManager = mDeps.getINetworkPolicyManager();
mNetd = mDeps.getINetd(mContext); mNetd = mDeps.getINetd(mContext);
@@ -225,10 +228,9 @@ public class Tethering {
mHandler = mTetherMasterSM.getHandler(); mHandler = mTetherMasterSM.getHandler();
mOffloadController = new OffloadController(mHandler, mOffloadController = new OffloadController(mHandler,
mDeps.getOffloadHardwareInterface(mHandler, mLog), mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(),
mContext.getContentResolver(), mNMService, mDeps.getINetworkManagementService(), mLog);
mLog); mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
mUpstreamNetworkMonitor = deps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
TetherMasterSM.EVENT_UPSTREAM_CALLBACK); TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
mForwardedDownstreams = new HashSet<>(); mForwardedDownstreams = new HashSet<>();
@@ -421,7 +423,6 @@ public class Tethering {
} }
} }
void interfaceRemoved(String iface) { void interfaceRemoved(String iface) {
if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
synchronized (mPublicSync) { synchronized (mPublicSync) {
@@ -1022,8 +1023,8 @@ public class Tethering {
String[] ifaces = null; String[] ifaces = null;
try { try {
ifaces = mNMService.listInterfaces(); ifaces = mNetd.interfaceGetList();
} catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "Error listing Interfaces", e); Log.e(TAG, "Error listing Interfaces", e);
return; return;
} }
@@ -1282,25 +1283,25 @@ public class Tethering {
protected boolean turnOnMasterTetherSettings() { protected boolean turnOnMasterTetherSettings() {
final TetheringConfiguration cfg = mConfig; final TetheringConfiguration cfg = mConfig;
try { try {
mNMService.setIpForwardingEnabled(true); mNetd.ipfwdEnableForwarding(TAG);
} catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) {
mLog.e(e); mLog.e(e);
transitionTo(mSetIpForwardingEnabledErrorState); transitionTo(mSetIpForwardingEnabledErrorState);
return false; return false;
} }
// TODO: Randomize DHCPv4 ranges, especially in hotspot mode. // TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
// Legacy DHCP server is disabled if passed an empty ranges array // Legacy DHCP server is disabled if passed an empty ranges array
final String[] dhcpRanges = cfg.enableLegacyDhcpServer final String[] dhcpRanges = cfg.enableLegacyDhcpServer
? cfg.legacyDhcpRanges ? cfg.legacyDhcpRanges : new String[0];
: new String[0];
try { try {
// TODO: Find a more accurate method name (startDHCPv4()?). NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges);
mNMService.startTethering(dhcpRanges); } catch (RemoteException | ServiceSpecificException e) {
} catch (Exception e) {
try { try {
mNMService.stopTethering(); // Stop and retry.
mNMService.startTethering(dhcpRanges); mNetd.tetherStop();
} catch (Exception ee) { NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges);
} catch (RemoteException | ServiceSpecificException ee) {
mLog.e(ee); mLog.e(ee);
transitionTo(mStartTetheringErrorState); transitionTo(mStartTetheringErrorState);
return false; return false;
@@ -1312,15 +1313,15 @@ public class Tethering {
protected boolean turnOffMasterTetherSettings() { protected boolean turnOffMasterTetherSettings() {
try { try {
mNMService.stopTethering(); mNetd.tetherStop();
} catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) {
mLog.e(e); mLog.e(e);
transitionTo(mStopTetheringErrorState); transitionTo(mStopTetheringErrorState);
return false; return false;
} }
try { try {
mNMService.setIpForwardingEnabled(false); mNetd.ipfwdDisableForwarding(TAG);
} catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) {
mLog.e(e); mLog.e(e);
transitionTo(mSetIpForwardingDisabledErrorState); transitionTo(mSetIpForwardingDisabledErrorState);
return false; return false;
@@ -1390,12 +1391,13 @@ public class Tethering {
// TODO: remove this invocation of NetworkUtils.makeStrings(). // TODO: remove this invocation of NetworkUtils.makeStrings().
dnsServers = NetworkUtils.makeStrings(dnses); dnsServers = NetworkUtils.makeStrings(dnses);
} }
final int netId = (network != null) ? network.netId : NETID_UNSET;
try { try {
mNMService.setDnsForwarders(network, dnsServers); mNetd.tetherDnsSet(netId, dnsServers);
mLog.log(String.format( mLog.log(String.format(
"SET DNS forwarders: network=%s dnsServers=%s", "SET DNS forwarders: network=%s dnsServers=%s",
network, Arrays.toString(dnsServers))); network, Arrays.toString(dnsServers)));
} catch (Exception e) { } catch (RemoteException | ServiceSpecificException e) {
// TODO: Investigate how this can fail and what exactly // TODO: Investigate how this can fail and what exactly
// happens if/when such failures occur. // happens if/when such failures occur.
mLog.e("setting DNS forwarders failed, " + e); mLog.e("setting DNS forwarders failed, " + e);
@@ -1698,8 +1700,8 @@ public class Tethering {
Log.e(TAG, "Error in startTethering"); Log.e(TAG, "Error in startTethering");
notify(IpServer.CMD_START_TETHERING_ERROR); notify(IpServer.CMD_START_TETHERING_ERROR);
try { try {
mNMService.setIpForwardingEnabled(false); mNetd.ipfwdDisableForwarding(TAG);
} catch (Exception e) { } } catch (RemoteException | ServiceSpecificException e) { }
} }
} }
@@ -1709,8 +1711,8 @@ public class Tethering {
Log.e(TAG, "Error in stopTethering"); Log.e(TAG, "Error in stopTethering");
notify(IpServer.CMD_STOP_TETHERING_ERROR); notify(IpServer.CMD_STOP_TETHERING_ERROR);
try { try {
mNMService.setIpForwardingEnabled(false); mNetd.ipfwdDisableForwarding(TAG);
} catch (Exception e) { } } catch (RemoteException | ServiceSpecificException e) { }
} }
} }
@@ -1720,11 +1722,11 @@ public class Tethering {
Log.e(TAG, "Error in setDnsForwarders"); Log.e(TAG, "Error in setDnsForwarders");
notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR); notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR);
try { try {
mNMService.stopTethering(); mNetd.tetherStop();
} catch (Exception e) { } } catch (RemoteException | ServiceSpecificException e) { }
try { try {
mNMService.setIpForwardingEnabled(false); mNetd.ipfwdDisableForwarding(TAG);
} catch (Exception e) { } } catch (RemoteException | ServiceSpecificException e) { }
} }
} }
@@ -1884,7 +1886,7 @@ public class Tethering {
} }
} }
void dump(FileDescriptor fd, PrintWriter writer, String[] args) { void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
// Binder.java closes the resource for us. // Binder.java closes the resource for us.
@SuppressWarnings("resource") @SuppressWarnings("resource")
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2065,7 +2067,7 @@ public class Tethering {
mLog.log("adding TetheringInterfaceStateMachine for: " + iface); mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
final TetherState tetherState = new TetherState( final TetherState tetherState = new TetherState(
new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService, new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mStatsService,
makeControlCallback(), mConfig.enableLegacyDhcpServer, makeControlCallback(), mConfig.enableLegacyDhcpServer,
mDeps.getIpServerDependencies())); mDeps.getIpServerDependencies()));
mTetherStates.put(iface, tetherState); mTetherStates.put(iface, tetherState);

View File

@@ -23,6 +23,7 @@ import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
import static android.net.INetd.IF_STATE_UP;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.ip.IpServer.STATE_AVAILABLE; import static android.net.ip.IpServer.STATE_AVAILABLE;
import static android.net.ip.IpServer.STATE_LOCAL_ONLY; import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
@@ -52,7 +53,7 @@ import static org.mockito.Mockito.when;
import android.net.INetd; import android.net.INetd;
import android.net.INetworkStatsService; import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration; import android.net.InterfaceConfigurationParcel;
import android.net.IpPrefix; import android.net.IpPrefix;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
@@ -64,7 +65,6 @@ import android.net.dhcp.IDhcpServerCallbacks;
import android.net.util.InterfaceParams; import android.net.util.InterfaceParams;
import android.net.util.InterfaceSet; import android.net.util.InterfaceSet;
import android.net.util.SharedLog; import android.net.util.SharedLog;
import android.os.INetworkManagementService;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.test.TestLooper; import android.os.test.TestLooper;
import android.text.TextUtils; import android.text.TextUtils;
@@ -89,6 +89,8 @@ public class IpServerTest {
private static final String IFACE_NAME = "testnet1"; private static final String IFACE_NAME = "testnet1";
private static final String UPSTREAM_IFACE = "upstream0"; private static final String UPSTREAM_IFACE = "upstream0";
private static final String UPSTREAM_IFACE2 = "upstream1"; private static final String UPSTREAM_IFACE2 = "upstream1";
private static final String BLUETOOTH_IFACE_ADDR = "192.168.42.1";
private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
private static final int DHCP_LEASE_TIME_SECS = 3600; private static final int DHCP_LEASE_TIME_SECS = 3600;
private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams( private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
@@ -96,11 +98,9 @@ public class IpServerTest {
private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000; private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000;
@Mock private INetworkManagementService mNMService;
@Mock private INetd mNetd; @Mock private INetd mNetd;
@Mock private INetworkStatsService mStatsService; @Mock private INetworkStatsService mStatsService;
@Mock private IpServer.Callback mCallback; @Mock private IpServer.Callback mCallback;
@Mock private InterfaceConfiguration mInterfaceConfiguration;
@Mock private SharedLog mSharedLog; @Mock private SharedLog mSharedLog;
@Mock private IDhcpServer mDhcpServer; @Mock private IDhcpServer mDhcpServer;
@Mock private RouterAdvertisementDaemon mRaDaemon; @Mock private RouterAdvertisementDaemon mRaDaemon;
@@ -112,6 +112,7 @@ public class IpServerTest {
private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor = private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
ArgumentCaptor.forClass(LinkProperties.class); ArgumentCaptor.forClass(LinkProperties.class);
private IpServer mIpServer; private IpServer mIpServer;
private InterfaceConfigurationParcel mInterfaceConfiguration;
private void initStateMachine(int interfaceType) throws Exception { private void initStateMachine(int interfaceType) throws Exception {
initStateMachine(interfaceType, false /* usingLegacyDhcp */); initStateMachine(interfaceType, false /* usingLegacyDhcp */);
@@ -131,17 +132,20 @@ public class IpServerTest {
}).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any()); }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon); when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS); when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
when(mDependencies.getNetdService()).thenReturn(mNetd); mInterfaceConfiguration = new InterfaceConfigurationParcel();
mInterfaceConfiguration.flags = new String[0];
if (interfaceType == TETHERING_BLUETOOTH) {
mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR;
mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH;
}
mIpServer = new IpServer( mIpServer = new IpServer(
IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, mStatsService,
mNMService, mStatsService, mCallback, usingLegacyDhcp, mDependencies); mCallback, usingLegacyDhcp, mDependencies);
mIpServer.start(); mIpServer.start();
// Starting the state machine always puts us in a consistent state and notifies // Starting the state machine always puts us in a consistent state and notifies
// the rest of the world that we've changed from an unknown to available state. // the rest of the world that we've changed from an unknown to available state.
mLooper.dispatchAll(); mLooper.dispatchAll();
reset(mNMService, mStatsService, mCallback); reset(mNetd, mStatsService, mCallback);
when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
when(mRaDaemon.start()).thenReturn(true); when(mRaDaemon.start()).thenReturn(true);
} }
@@ -158,8 +162,7 @@ public class IpServerTest {
if (upstreamIface != null) { if (upstreamIface != null) {
dispatchTetherConnectionChanged(upstreamIface); dispatchTetherConnectionChanged(upstreamIface);
} }
reset(mNMService, mStatsService, mCallback); reset(mNetd, mStatsService, mCallback);
when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
} }
@Before public void setUp() throws Exception { @Before public void setUp() throws Exception {
@@ -169,15 +172,14 @@ public class IpServerTest {
@Test @Test
public void startsOutAvailable() { public void startsOutAvailable() {
mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mCallback, mNetd, mStatsService, mCallback, false /* usingLegacyDhcp */, mDependencies);
false /* usingLegacyDhcp */, mDependencies);
mIpServer.start(); mIpServer.start();
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mCallback).updateInterfaceState( verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class)); verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
verifyNoMoreInteractions(mCallback, mNMService, mStatsService); verifyNoMoreInteractions(mCallback, mNetd, mStatsService);
} }
@Test @Test
@@ -196,7 +198,7 @@ public class IpServerTest {
// None of these commands should trigger us to request action from // None of these commands should trigger us to request action from
// the rest of the system. // the rest of the system.
dispatchCommand(command); dispatchCommand(command);
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
} }
@@ -208,7 +210,7 @@ public class IpServerTest {
verify(mCallback).updateInterfaceState( verify(mCallback).updateInterfaceState(
mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR); mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class)); verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
@Test @Test
@@ -216,13 +218,17 @@ public class IpServerTest {
initStateMachine(TETHERING_BLUETOOTH); initStateMachine(TETHERING_BLUETOOTH);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
InOrder inOrder = inOrder(mCallback, mNMService); InOrder inOrder = inOrder(mCallback, mNetd);
inOrder.verify(mNMService).tetherInterface(IFACE_NAME); inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
// One for ipv4 route, one for ipv6 link local route.
inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
any(), any());
inOrder.verify(mCallback).updateInterfaceState( inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR); mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties( inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class)); eq(mIpServer), any(LinkProperties.class));
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
@Test @Test
@@ -230,14 +236,16 @@ public class IpServerTest {
initTetheredStateMachine(TETHERING_BLUETOOTH, null); initTetheredStateMachine(TETHERING_BLUETOOTH, null);
dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
InOrder inOrder = inOrder(mNMService, mNetd, mStatsService, mCallback); InOrder inOrder = inOrder(mNetd, mStatsService, mCallback);
inOrder.verify(mNMService).untetherInterface(IFACE_NAME); inOrder.verify(mNetd).tetherApplyDnsInterfaces();
inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
inOrder.verify(mCallback).updateInterfaceState( inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties( inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class)); eq(mIpServer), any(LinkProperties.class));
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
@Test @Test
@@ -245,16 +253,19 @@ public class IpServerTest {
initStateMachine(TETHERING_USB); initStateMachine(TETHERING_USB);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
InOrder inOrder = inOrder(mCallback, mNMService); InOrder inOrder = inOrder(mCallback, mNetd);
inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME); inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration); IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
inOrder.verify(mNMService).tetherInterface(IFACE_NAME); inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
any(), any());
inOrder.verify(mCallback).updateInterfaceState( inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR); mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties( inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), mLinkPropertiesCaptor.capture()); eq(mIpServer), mLinkPropertiesCaptor.capture());
assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue()); assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
@Test @Test
@@ -262,16 +273,19 @@ public class IpServerTest {
initStateMachine(TETHERING_WIFI_P2P); initStateMachine(TETHERING_WIFI_P2P);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY); dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
InOrder inOrder = inOrder(mCallback, mNMService); InOrder inOrder = inOrder(mCallback, mNetd);
inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME); inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration); IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
inOrder.verify(mNMService).tetherInterface(IFACE_NAME); inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
any(), any());
inOrder.verify(mCallback).updateInterfaceState( inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR); mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties( inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), mLinkPropertiesCaptor.capture()); eq(mIpServer), mLinkPropertiesCaptor.capture());
assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue()); assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
@Test @Test
@@ -281,10 +295,10 @@ public class IpServerTest {
// Telling the state machine about its upstream interface triggers // Telling the state machine about its upstream interface triggers
// a little more configuration. // a little more configuration.
dispatchTetherConnectionChanged(UPSTREAM_IFACE); dispatchTetherConnectionChanged(UPSTREAM_IFACE);
InOrder inOrder = inOrder(mNMService); InOrder inOrder = inOrder(mNetd);
inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
@Test @Test
@@ -292,49 +306,49 @@ public class IpServerTest {
initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2); dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
InOrder inOrder = inOrder(mNMService, mStatsService); InOrder inOrder = inOrder(mNetd, mStatsService);
inOrder.verify(mStatsService).forceUpdate(); inOrder.verify(mStatsService).forceUpdate();
inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2); inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2); inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
@Test @Test
public void handlesChangingUpstreamNatFailure() throws Exception { public void handlesChangingUpstreamNatFailure() throws Exception {
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
doThrow(RemoteException.class).when(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2); doThrow(RemoteException.class).when(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2); dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
InOrder inOrder = inOrder(mNMService, mStatsService); InOrder inOrder = inOrder(mNetd, mStatsService);
inOrder.verify(mStatsService).forceUpdate(); inOrder.verify(mStatsService).forceUpdate();
inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2); inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mStatsService).forceUpdate(); inOrder.verify(mStatsService).forceUpdate();
inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2); inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2); inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
} }
@Test @Test
public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception { public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
doThrow(RemoteException.class).when(mNMService).startInterfaceForwarding( doThrow(RemoteException.class).when(mNetd).ipfwdAddInterfaceForward(
IFACE_NAME, UPSTREAM_IFACE2); IFACE_NAME, UPSTREAM_IFACE2);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2); dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
InOrder inOrder = inOrder(mNMService, mStatsService); InOrder inOrder = inOrder(mNetd, mStatsService);
inOrder.verify(mStatsService).forceUpdate(); inOrder.verify(mStatsService).forceUpdate();
inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2); inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2); inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mStatsService).forceUpdate(); inOrder.verify(mStatsService).forceUpdate();
inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2); inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2); inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
} }
@Test @Test
@@ -342,17 +356,19 @@ public class IpServerTest {
initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE); initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED); dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
InOrder inOrder = inOrder(mNMService, mNetd, mStatsService, mCallback); InOrder inOrder = inOrder(mNetd, mStatsService, mCallback);
inOrder.verify(mStatsService).forceUpdate(); inOrder.verify(mStatsService).forceUpdate();
inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE); inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).untetherInterface(IFACE_NAME); inOrder.verify(mNetd).tetherApplyDnsInterfaces();
inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName))); inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
inOrder.verify(mCallback).updateInterfaceState( inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR); mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties( inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class)); eq(mIpServer), any(LinkProperties.class));
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
@Test @Test
@@ -361,13 +377,14 @@ public class IpServerTest {
initTetheredStateMachine(TETHERING_USB, null); initTetheredStateMachine(TETHERING_USB, null);
if (shouldThrow) { if (shouldThrow) {
doThrow(RemoteException.class).when(mNMService).untetherInterface(IFACE_NAME); doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME);
} }
dispatchCommand(IpServer.CMD_INTERFACE_DOWN); dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback); InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown(); // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down
usbTeardownOrder.verify(mNMService).setInterfaceConfig( // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address.
IFACE_NAME, mInterfaceConfiguration); usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState( usbTeardownOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR); mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties( usbTeardownOrder.verify(mCallback).updateLinkProperties(
@@ -380,12 +397,15 @@ public class IpServerTest {
public void usbShouldBeTornDownOnTetherError() throws Exception { public void usbShouldBeTornDownOnTetherError() throws Exception {
initStateMachine(TETHERING_USB); initStateMachine(TETHERING_USB);
doThrow(RemoteException.class).when(mNMService).tetherInterface(IFACE_NAME); doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback); InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown(); usbTeardownOrder.verify(mNetd).interfaceSetCfg(
usbTeardownOrder.verify(mNMService).setInterfaceConfig( argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
IFACE_NAME, mInterfaceConfiguration); usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState( usbTeardownOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR); mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties( usbTeardownOrder.verify(mCallback).updateLinkProperties(
@@ -397,11 +417,13 @@ public class IpServerTest {
public void shouldTearDownUsbOnUpstreamError() throws Exception { public void shouldTearDownUsbOnUpstreamError() throws Exception {
initTetheredStateMachine(TETHERING_USB, null); initTetheredStateMachine(TETHERING_USB, null);
doThrow(RemoteException.class).when(mNMService).enableNat(anyString(), anyString()); doThrow(RemoteException.class).when(mNetd).tetherAddForward(anyString(), anyString());
dispatchTetherConnectionChanged(UPSTREAM_IFACE); dispatchTetherConnectionChanged(UPSTREAM_IFACE);
InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback); InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown(); usbTeardownOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
usbTeardownOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState( usbTeardownOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR); mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties( usbTeardownOrder.verify(mCallback).updateLinkProperties(
@@ -413,11 +435,11 @@ public class IpServerTest {
public void ignoresDuplicateUpstreamNotifications() throws Exception { public void ignoresDuplicateUpstreamNotifications() throws Exception {
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
dispatchTetherConnectionChanged(UPSTREAM_IFACE); dispatchTetherConnectionChanged(UPSTREAM_IFACE);
verifyNoMoreInteractions(mNMService, mStatsService, mCallback); verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
} }
} }
@@ -525,4 +547,12 @@ public class IpServerTest {
// never see an empty interface name in any LinkProperties update. // never see an empty interface name in any LinkProperties update.
assertFalse(TextUtils.isEmpty(lp.getInterfaceName())); assertFalse(TextUtils.isEmpty(lp.getInterfaceName()));
} }
private boolean assertContainsFlag(String[] flags, String match) {
for (String flag : flags) {
if (flag.equals(match)) return true;
}
fail("Missing flag: " + match);
return false;
}
} }

View File

@@ -50,7 +50,6 @@ import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
@@ -74,7 +73,7 @@ import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService; import android.net.INetworkStatsService;
import android.net.ITetheringEventCallback; import android.net.ITetheringEventCallback;
import android.net.InetAddresses; import android.net.InetAddresses;
import android.net.InterfaceConfiguration; import android.net.InterfaceConfigurationParcel;
import android.net.IpPrefix; import android.net.IpPrefix;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
@@ -147,6 +146,7 @@ public class TetheringTest {
private static final String TEST_USB_IFNAME = "test_rndis0"; private static final String TEST_USB_IFNAME = "test_rndis0";
private static final String TEST_WLAN_IFNAME = "test_wlan0"; private static final String TEST_WLAN_IFNAME = "test_wlan0";
private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0"; private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
private static final String TETHERING_NAME = "Tethering";
private static final int DHCPSERVER_START_TIMEOUT_MS = 1000; private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
@@ -185,6 +185,7 @@ public class TetheringTest {
private BroadcastReceiver mBroadcastReceiver; private BroadcastReceiver mBroadcastReceiver;
private Tethering mTethering; private Tethering mTethering;
private PhoneStateListener mPhoneStateListener; private PhoneStateListener mPhoneStateListener;
private InterfaceConfigurationParcel mInterfaceConfiguration;
private class TestContext extends BroadcastInterceptingContext { private class TestContext extends BroadcastInterceptingContext {
TestContext(Context base) { TestContext(Context base) {
@@ -247,11 +248,6 @@ public class TetheringTest {
MacAddress.ALL_ZEROS_ADDRESS); MacAddress.ALL_ZEROS_ADDRESS);
} }
@Override
public INetd getNetdService() {
return mNetd;
}
@Override @Override
public void makeDhcpServer(String ifName, DhcpServingParamsParcel params, public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
DhcpServerCallbacks cb) { DhcpServerCallbacks cb) {
@@ -429,11 +425,11 @@ public class TetheringTest {
.thenReturn(new int[0]); .thenReturn(new int[0]);
when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic)) when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
.thenReturn(false); .thenReturn(false);
when(mNMService.listInterfaces()) when(mNetd.interfaceGetList())
.thenReturn(new String[] { .thenReturn(new String[] {
TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME}); TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME});
when(mNMService.getInterfaceConfig(anyString())) mInterfaceConfiguration = new InterfaceConfigurationParcel();
.thenReturn(new InterfaceConfiguration()); mInterfaceConfiguration.flags = new String[0];
when(mRouterAdvertisementDaemon.start()) when(mRouterAdvertisementDaemon.start())
.thenReturn(true); .thenReturn(true);
@@ -523,10 +519,11 @@ public class TetheringTest {
} }
private void verifyInterfaceServingModeStarted(String ifname) throws Exception { private void verifyInterfaceServingModeStarted(String ifname) throws Exception {
verify(mNMService, times(1)).getInterfaceConfig(ifname); verify(mNetd, times(1)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
verify(mNMService, times(1)) verify(mNetd, times(1)).tetherInterfaceAdd(ifname);
.setInterfaceConfig(eq(ifname), any(InterfaceConfiguration.class)); verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, ifname);
verify(mNMService, times(1)).tetherInterface(ifname); verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(ifname),
anyString(), anyString());
} }
private void verifyTetheringBroadcast(String ifname, String whichExtra) { private void verifyTetheringBroadcast(String ifname, String whichExtra) {
@@ -558,7 +555,7 @@ public class TetheringTest {
verify(mWifiManager).updateInterfaceIpState( verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
} }
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mWifiManager);
} }
@@ -581,14 +578,14 @@ public class TetheringTest {
prepareUsbTethering(upstreamState); prepareUsbTethering(upstreamState);
// This should produce no activity of any kind. // This should produce no activity of any kind.
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
// Pretend we then receive USB configured broadcast. // Pretend we then receive USB configured broadcast.
sendUsbBroadcast(true, true, true); sendUsbBroadcast(true, true, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
// Now we should see the start of tethering mechanics (in this case: // Now we should see the start of tethering mechanics (in this case:
// tetherMatchingInterfaces() which starts by fetching all interfaces). // tetherMatchingInterfaces() which starts by fetching all interfaces).
verify(mNMService, times(1)).listInterfaces(); verify(mNetd, times(1)).interfaceGetList();
// UpstreamNetworkMonitor should receive selected upstream // UpstreamNetworkMonitor should receive selected upstream
verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any()); verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
@@ -618,9 +615,9 @@ public class TetheringTest {
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME); verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
verify(mNMService, times(1)).setIpForwardingEnabled(true); verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
verify(mNMService, times(1)).startTethering(any(String[].class)); verify(mNetd, times(1)).tetherStartWithConfiguration(any());
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
verify(mWifiManager).updateInterfaceIpState( verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verify(mWifiManager).updateInterfaceIpState( verify(mWifiManager).updateInterfaceIpState(
@@ -638,16 +635,16 @@ public class TetheringTest {
mTethering.interfaceRemoved(TEST_WLAN_IFNAME); mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME); verify(mNetd, times(1)).tetherApplyDnsInterfaces();
// {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4. verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME); verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
verify(mNMService, times(2)) // interfaceSetCfg() called once for enabling and twice disabling IPv4.
.setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class)); verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
verify(mNMService, times(1)).stopTethering(); verify(mNetd, times(1)).tetherStop();
verify(mNMService, times(1)).setIpForwardingEnabled(false); verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
verify(mWifiManager, times(3)).updateInterfaceIpState( verify(mWifiManager, times(3)).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mWifiManager);
// Asking for the last error after the per-interface state machine // Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error. // has been reaped yields an unknown interface error.
@@ -684,8 +681,8 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState(); UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
runUsbTethering(upstreamState); runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
sendIPv6TetherUpdates(upstreamState); sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull()); verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
@@ -708,8 +705,8 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState(); UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState); runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
sendIPv6TetherUpdates(upstreamState); sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull()); verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
@@ -721,8 +718,8 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState(); UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
runUsbTethering(upstreamState); runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mRouterAdvertisementDaemon, times(1)).start(); verify(mRouterAdvertisementDaemon, times(1)).start();
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any()); verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
@@ -736,12 +733,11 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobile464xlatUpstreamState(); UpstreamNetworkState upstreamState = buildMobile464xlatUpstreamState();
runUsbTethering(upstreamState); runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME); verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any()); verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
TEST_XLAT_MOBILE_IFNAME);
sendIPv6TetherUpdates(upstreamState); sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull()); verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
@@ -754,9 +750,9 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState(); UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState); runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any()); verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
// Then 464xlat comes up // Then 464xlat comes up
upstreamState = buildMobile464xlatUpstreamState(); upstreamState = buildMobile464xlatUpstreamState();
@@ -772,12 +768,11 @@ public class TetheringTest {
mLooper.dispatchAll(); mLooper.dispatchAll();
// Forwarding is added for 464xlat // Forwarding is added for 464xlat
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME); verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
TEST_XLAT_MOBILE_IFNAME);
// Forwarding was not re-added for v6 (still times(1)) // Forwarding was not re-added for v6 (still times(1))
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
// DHCP not restarted on downstream (still times(1)) // DHCP not restarted on downstream (still times(1))
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any()); verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
} }
@@ -820,7 +815,7 @@ public class TetheringTest {
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null); verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, causing the // Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that // per-interface state machine to start up, and telling us that
@@ -833,7 +828,7 @@ public class TetheringTest {
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
verify(mWifiManager).updateInterfaceIpState( verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mWifiManager);
} }
@@ -847,7 +842,7 @@ public class TetheringTest {
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null); verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, causing the // Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that // per-interface state machine to start up, and telling us that
@@ -858,9 +853,11 @@ public class TetheringTest {
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME); verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
verify(mNMService, times(1)).setIpForwardingEnabled(true); verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
verify(mNMService, times(1)).startTethering(any(String[].class)); verify(mNetd, times(1)).tetherStartWithConfiguration(any());
verifyNoMoreInteractions(mNMService); verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME),
anyString(), anyString());
verifyNoMoreInteractions(mNetd);
verify(mWifiManager).updateInterfaceIpState( verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verify(mWifiManager).updateInterfaceIpState( verify(mWifiManager).updateInterfaceIpState(
@@ -878,8 +875,8 @@ public class TetheringTest {
///// /////
// We do not currently emulate any upstream being found. // We do not currently emulate any upstream being found.
// //
// This is why there are no calls to verify mNMService.enableNat() or // This is why there are no calls to verify mNetd.tetherAddForward() or
// mNMService.startInterfaceForwarding(). // mNetd.ipfwdAddInterfaceForward().
///// /////
// Emulate pressing the WiFi tethering button. // Emulate pressing the WiFi tethering button.
@@ -887,7 +884,7 @@ public class TetheringTest {
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mWifiManager, times(1)).stopSoftAp(); verify(mWifiManager, times(1)).stopSoftAp();
verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, when tethering mode // Emulate externally-visible WifiManager effects, when tethering mode
// is being torn down. // is being torn down.
@@ -895,16 +892,16 @@ public class TetheringTest {
mTethering.interfaceRemoved(TEST_WLAN_IFNAME); mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME); verify(mNetd, times(1)).tetherApplyDnsInterfaces();
// {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4. verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME); verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
verify(mNMService, atLeastOnce()) // interfaceSetCfg() called once for enabling and twice for disabling IPv4.
.setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class)); verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
verify(mNMService, times(1)).stopTethering(); verify(mNetd, times(1)).tetherStop();
verify(mNMService, times(1)).setIpForwardingEnabled(false); verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
verify(mWifiManager, times(3)).updateInterfaceIpState( verify(mWifiManager, times(3)).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mWifiManager);
// Asking for the last error after the per-interface state machine // Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error. // has been reaped yields an unknown interface error.
@@ -915,14 +912,14 @@ public class TetheringTest {
@Test @Test
public void failureEnablingIpForwarding() throws Exception { public void failureEnablingIpForwarding() throws Exception {
when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true); when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true); doThrow(new RemoteException()).when(mNetd).ipfwdEnableForwarding(TETHERING_NAME);
// Emulate pressing the WiFi tethering button. // Emulate pressing the WiFi tethering button.
mTethering.startTethering(TETHERING_WIFI, null, false); mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null); verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, causing the // Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that // per-interface state machine to start up, and telling us that
@@ -931,15 +928,15 @@ public class TetheringTest {
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED); sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll(); mLooper.dispatchAll();
// We verify get/set called thrice here: twice for setup (on NMService) and once during // We verify get/set called three times here: twice for setup and once during
// teardown (on Netd) because all events happen over the course of the single // teardown because all events happen over the course of the single
// dispatchAll() above. Note that once the IpServer IPv4 address config // dispatchAll() above. Note that once the IpServer IPv4 address config
// code is refactored the two calls during shutdown will revert to one. // code is refactored the two calls during shutdown will revert to one.
verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME); verify(mNetd, times(3)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName)));
verify(mNMService, times(2)) verify(mNetd, times(1)).tetherInterfaceAdd(TEST_WLAN_IFNAME);
.setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class)); verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
verify(mNetd, times(1)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName))); verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME),
verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME); anyString(), anyString());
verify(mWifiManager).updateInterfaceIpState( verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED); TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verify(mWifiManager).updateInterfaceIpState( verify(mWifiManager).updateInterfaceIpState(
@@ -949,18 +946,20 @@ public class TetheringTest {
assertEquals(3, mTetheringDependencies.mIsTetheringSupportedCalls); assertEquals(3, mTetheringDependencies.mIsTetheringSupportedCalls);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
// This is called, but will throw. // This is called, but will throw.
verify(mNMService, times(1)).setIpForwardingEnabled(true); verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
// This never gets called because of the exception thrown above. // This never gets called because of the exception thrown above.
verify(mNMService, times(0)).startTethering(any(String[].class)); verify(mNetd, times(0)).tetherStartWithConfiguration(any());
// When the master state machine transitions to an error state it tells // When the master state machine transitions to an error state it tells
// downstream interfaces, which causes us to tell Wi-Fi about the error // downstream interfaces, which causes us to tell Wi-Fi about the error
// so it can take down AP mode. // so it can take down AP mode.
verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME); verify(mNetd, times(1)).tetherApplyDnsInterfaces();
verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
verify(mWifiManager).updateInterfaceIpState( verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR); TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
verifyNoMoreInteractions(mWifiManager); verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
} }
private void runUserRestrictionsChange( private void runUserRestrictionsChange(
@@ -1232,9 +1231,9 @@ public class TetheringTest {
verifyInterfaceServingModeStarted(TEST_P2P_IFNAME); verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER); verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
verify(mNMService, times(1)).setIpForwardingEnabled(true); verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
verify(mNMService, times(1)).startTethering(any(String[].class)); verify(mNetd, times(1)).tetherStartWithConfiguration(any());
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY); verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks(); verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
// This will be called twice, one is on entering IpServer.STATE_AVAILABLE, // This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
@@ -1249,16 +1248,16 @@ public class TetheringTest {
mTethering.interfaceRemoved(TEST_P2P_IFNAME); mTethering.interfaceRemoved(TEST_P2P_IFNAME);
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mNMService, times(1)).untetherInterface(TEST_P2P_IFNAME); verify(mNetd, times(1)).tetherApplyDnsInterfaces();
// {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4. verify(mNetd, times(1)).tetherInterfaceRemove(TEST_P2P_IFNAME);
verify(mNMService, times(2)).getInterfaceConfig(TEST_P2P_IFNAME); verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
verify(mNMService, times(2)) // interfaceSetCfg() called once for enabling and twice for disabling IPv4.
.setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class)); verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
verify(mNMService, times(1)).stopTethering(); verify(mNetd, times(1)).tetherStop();
verify(mNMService, times(1)).setIpForwardingEnabled(false); verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
verify(mUpstreamNetworkMonitor, never()).getCurrentPreferredUpstream(); verify(mUpstreamNetworkMonitor, never()).getCurrentPreferredUpstream();
verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any()); verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
// Asking for the last error after the per-interface state machine // Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error. // has been reaped yields an unknown interface error.
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME)); assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
@@ -1272,12 +1271,11 @@ public class TetheringTest {
sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME); sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME);
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME); verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
verify(mNMService, never()) verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
.setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class)); verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME); verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
verify(mNMService, never()).setIpForwardingEnabled(true); verify(mNetd, never()).tetherStartWithConfiguration(any());
verify(mNMService, never()).startTethering(any(String[].class));
// Emulate externally-visible WifiP2pManager effects, when wifi p2p group // Emulate externally-visible WifiP2pManager effects, when wifi p2p group
// is being removed. // is being removed.
@@ -1285,13 +1283,13 @@ public class TetheringTest {
mTethering.interfaceRemoved(TEST_P2P_IFNAME); mTethering.interfaceRemoved(TEST_P2P_IFNAME);
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mNMService, never()).untetherInterface(TEST_P2P_IFNAME); verify(mNetd, never()).tetherApplyDnsInterfaces();
verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME); verify(mNetd, never()).tetherInterfaceRemove(TEST_P2P_IFNAME);
verify(mNMService, never()) verify(mNetd, never()).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
.setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class)); verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
verify(mNMService, never()).stopTethering(); verify(mNetd, never()).tetherStop();
verify(mNMService, never()).setIpForwardingEnabled(false); verify(mNetd, never()).ipfwdDisableForwarding(TETHERING_NAME);
verifyNoMoreInteractions(mNMService); verifyNoMoreInteractions(mNetd);
// Asking for the last error after the per-interface state machine // Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error. // has been reaped yields an unknown interface error.
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME)); assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
@@ -1321,12 +1319,11 @@ public class TetheringTest {
sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME); sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
mLooper.dispatchAll(); mLooper.dispatchAll();
verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME); verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
verify(mNMService, never()) verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
.setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class)); verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME); verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
verify(mNMService, never()).setIpForwardingEnabled(true); verify(mNetd, never()).tetherStartWithConfiguration(any());
verify(mNMService, never()).startTethering(any(String[].class));
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME)); assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
} }
@Test @Test