Merge "Initial rename to IpServer"
This commit is contained in:
@@ -68,6 +68,7 @@ import android.content.res.Resources;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.net.INetworkPolicyManager;
|
||||
import android.net.INetworkStatsService;
|
||||
import android.net.ip.IpServer;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
@@ -112,10 +113,8 @@ import com.android.internal.util.Protocol;
|
||||
import com.android.internal.util.State;
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.connectivity.tethering.IControlsTethering;
|
||||
import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
|
||||
import com.android.server.connectivity.tethering.OffloadController;
|
||||
import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
|
||||
import com.android.server.connectivity.tethering.TetheringConfiguration;
|
||||
import com.android.server.connectivity.tethering.TetheringDependencies;
|
||||
import com.android.server.connectivity.tethering.TetheringInterfaceUtils;
|
||||
@@ -149,7 +148,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning";
|
||||
|
||||
private static final Class[] messageClasses = {
|
||||
Tethering.class, TetherMasterSM.class, TetherInterfaceStateMachine.class
|
||||
Tethering.class, TetherMasterSM.class, IpServer.class
|
||||
};
|
||||
private static final SparseArray<String> sMagicDecoderRing =
|
||||
MessageUtils.findMessageNames(messageClasses);
|
||||
@@ -159,21 +158,21 @@ public class Tethering extends BaseNetworkObserver {
|
||||
.getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
|
||||
|
||||
private static class TetherState {
|
||||
public final TetherInterfaceStateMachine stateMachine;
|
||||
public final IpServer ipServer;
|
||||
public int lastState;
|
||||
public int lastError;
|
||||
|
||||
public TetherState(TetherInterfaceStateMachine sm) {
|
||||
stateMachine = sm;
|
||||
public TetherState(IpServer ipServer) {
|
||||
this.ipServer = ipServer;
|
||||
// Assume all state machines start out available and with no errors.
|
||||
lastState = IControlsTethering.STATE_AVAILABLE;
|
||||
lastState = IpServer.STATE_AVAILABLE;
|
||||
lastError = TETHER_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
public boolean isCurrentlyServing() {
|
||||
switch (lastState) {
|
||||
case IControlsTethering.STATE_TETHERED:
|
||||
case IControlsTethering.STATE_LOCAL_ONLY:
|
||||
case IpServer.STATE_TETHERED:
|
||||
case IpServer.STATE_LOCAL_ONLY:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -198,7 +197,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
|
||||
// TODO: Figure out how to merge this and other downstream-tracking objects
|
||||
// into a single coherent structure.
|
||||
private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams;
|
||||
private final HashSet<IpServer> mForwardedDownstreams;
|
||||
private final VersionedBroadcastListener mCarrierConfigChange;
|
||||
private final TetheringDependencies mDeps;
|
||||
|
||||
@@ -604,7 +603,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
|
||||
public int tether(String iface) {
|
||||
return tether(iface, IControlsTethering.STATE_TETHERED);
|
||||
return tether(iface, IpServer.STATE_TETHERED);
|
||||
}
|
||||
|
||||
private int tether(String iface, int requestedState) {
|
||||
@@ -617,7 +616,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
// Ignore the error status of the interface. If the interface is available,
|
||||
// the errors are referring to past tethering attempts anyway.
|
||||
if (tetherState.lastState != IControlsTethering.STATE_AVAILABLE) {
|
||||
if (tetherState.lastState != IpServer.STATE_AVAILABLE) {
|
||||
Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
|
||||
return TETHER_ERROR_UNAVAIL_IFACE;
|
||||
}
|
||||
@@ -626,8 +625,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
// return an error.
|
||||
//
|
||||
// TODO: reexamine the threading and messaging model.
|
||||
tetherState.stateMachine.sendMessage(
|
||||
TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, requestedState);
|
||||
tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_REQUESTED, requestedState);
|
||||
return TETHER_ERROR_NO_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -644,8 +642,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring");
|
||||
return TETHER_ERROR_UNAVAIL_IFACE;
|
||||
}
|
||||
tetherState.stateMachine.sendMessage(
|
||||
TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
|
||||
tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_UNREQUESTED);
|
||||
return TETHER_ERROR_NO_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -689,11 +686,11 @@ public class Tethering extends BaseNetworkObserver {
|
||||
String iface = mTetherStates.keyAt(i);
|
||||
if (tetherState.lastError != TETHER_ERROR_NO_ERROR) {
|
||||
erroredList.add(iface);
|
||||
} else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
|
||||
} else if (tetherState.lastState == IpServer.STATE_AVAILABLE) {
|
||||
availableList.add(iface);
|
||||
} else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_ONLY) {
|
||||
} else if (tetherState.lastState == IpServer.STATE_LOCAL_ONLY) {
|
||||
localOnlyList.add(iface);
|
||||
} else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
|
||||
} else if (tetherState.lastState == IpServer.STATE_TETHERED) {
|
||||
if (cfg.isUsb(iface)) {
|
||||
usbTethered = true;
|
||||
} else if (cfg.isWifi(iface)) {
|
||||
@@ -882,10 +879,10 @@ public class Tethering extends BaseNetworkObserver {
|
||||
synchronized (Tethering.this.mPublicSync) {
|
||||
if (!usbConnected && mRndisEnabled) {
|
||||
// Turn off tethering if it was enabled and there is a disconnect.
|
||||
tetherMatchingInterfaces(IControlsTethering.STATE_AVAILABLE, TETHERING_USB);
|
||||
tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB);
|
||||
} else if (usbConfigured && rndisEnabled) {
|
||||
// Tether if rndis is enabled and usb is configured.
|
||||
tetherMatchingInterfaces(IControlsTethering.STATE_TETHERED, TETHERING_USB);
|
||||
tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB);
|
||||
}
|
||||
mRndisEnabled = usbConfigured && rndisEnabled;
|
||||
}
|
||||
@@ -959,15 +956,15 @@ public class Tethering extends BaseNetworkObserver {
|
||||
if (!TextUtils.isEmpty(ifname)) {
|
||||
final TetherState ts = mTetherStates.get(ifname);
|
||||
if (ts != null) {
|
||||
ts.stateMachine.unwanted();
|
||||
ts.ipServer.unwanted();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||
TetherInterfaceStateMachine tism = mTetherStates.valueAt(i).stateMachine;
|
||||
if (tism.interfaceType() == TETHERING_WIFI) {
|
||||
tism.unwanted();
|
||||
final IpServer ipServer = mTetherStates.valueAt(i).ipServer;
|
||||
if (ipServer.interfaceType() == TETHERING_WIFI) {
|
||||
ipServer.unwanted();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -978,15 +975,15 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
|
||||
private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
|
||||
// Map wifiIpMode values to IControlsTethering serving states, inferring
|
||||
// Map wifiIpMode values to IpServer.Callback serving states, inferring
|
||||
// from mWifiTetherRequested as a final "best guess".
|
||||
final int ipServingMode;
|
||||
switch (wifiIpMode) {
|
||||
case IFACE_IP_MODE_TETHERED:
|
||||
ipServingMode = IControlsTethering.STATE_TETHERED;
|
||||
ipServingMode = IpServer.STATE_TETHERED;
|
||||
break;
|
||||
case IFACE_IP_MODE_LOCAL_ONLY:
|
||||
ipServingMode = IControlsTethering.STATE_LOCAL_ONLY;
|
||||
ipServingMode = IpServer.STATE_LOCAL_ONLY;
|
||||
break;
|
||||
default:
|
||||
mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
|
||||
@@ -1041,12 +1038,12 @@ public class Tethering extends BaseNetworkObserver {
|
||||
private void changeInterfaceState(String ifname, int requestedState) {
|
||||
final int result;
|
||||
switch (requestedState) {
|
||||
case IControlsTethering.STATE_UNAVAILABLE:
|
||||
case IControlsTethering.STATE_AVAILABLE:
|
||||
case IpServer.STATE_UNAVAILABLE:
|
||||
case IpServer.STATE_AVAILABLE:
|
||||
result = untether(ifname);
|
||||
break;
|
||||
case IControlsTethering.STATE_TETHERED:
|
||||
case IControlsTethering.STATE_LOCAL_ONLY:
|
||||
case IpServer.STATE_TETHERED:
|
||||
case IpServer.STATE_LOCAL_ONLY:
|
||||
result = tether(ifname, requestedState);
|
||||
break;
|
||||
default:
|
||||
@@ -1104,7 +1101,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
synchronized (mPublicSync) {
|
||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||
TetherState tetherState = mTetherStates.valueAt(i);
|
||||
if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
|
||||
if (tetherState.lastState == IpServer.STATE_TETHERED) {
|
||||
list.add(mTetherStates.keyAt(i));
|
||||
}
|
||||
}
|
||||
@@ -1117,7 +1114,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
synchronized (mPublicSync) {
|
||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||
TetherState tetherState = mTetherStates.valueAt(i);
|
||||
if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
|
||||
if (tetherState.lastState == IpServer.STATE_AVAILABLE) {
|
||||
list.add(mTetherStates.keyAt(i));
|
||||
}
|
||||
}
|
||||
@@ -1177,7 +1174,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
synchronized (mPublicSync) {
|
||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||
TetherState tetherState = mTetherStates.valueAt(i);
|
||||
if (tetherState.lastState != IControlsTethering.STATE_TETHERED) {
|
||||
if (tetherState.lastState != IpServer.STATE_TETHERED) {
|
||||
continue; // Skip interfaces that aren't tethered.
|
||||
}
|
||||
String iface = mTetherStates.keyAt(i);
|
||||
@@ -1231,7 +1228,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
// Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList
|
||||
// so that the garbage collector does not clean up the state machine before it has a chance
|
||||
// to tear itself down.
|
||||
private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
|
||||
private final ArrayList<IpServer> mNotifyList;
|
||||
private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
|
||||
private final OffloadWrapper mOffload;
|
||||
|
||||
@@ -1268,17 +1265,19 @@ public class Tethering extends BaseNetworkObserver {
|
||||
public boolean processMessage(Message message) {
|
||||
logMessage(this, message.what);
|
||||
switch (message.what) {
|
||||
case EVENT_IFACE_SERVING_STATE_ACTIVE:
|
||||
TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
|
||||
case EVENT_IFACE_SERVING_STATE_ACTIVE: {
|
||||
final IpServer who = (IpServer) message.obj;
|
||||
if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
|
||||
handleInterfaceServingStateActive(message.arg1, who);
|
||||
transitionTo(mTetherModeAliveState);
|
||||
break;
|
||||
case EVENT_IFACE_SERVING_STATE_INACTIVE:
|
||||
who = (TetherInterfaceStateMachine) message.obj;
|
||||
}
|
||||
case EVENT_IFACE_SERVING_STATE_INACTIVE: {
|
||||
final IpServer who = (IpServer) message.obj;
|
||||
if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
|
||||
handleInterfaceServingStateInactive(who);
|
||||
break;
|
||||
}
|
||||
case EVENT_IFACE_UPDATE_LINKPROPERTIES:
|
||||
// Silently ignore these for now.
|
||||
break;
|
||||
@@ -1410,8 +1409,8 @@ public class Tethering extends BaseNetworkObserver {
|
||||
|
||||
protected void notifyDownstreamsOfNewUpstreamIface(InterfaceSet ifaces) {
|
||||
mCurrentUpstreamIfaceSet = ifaces;
|
||||
for (TetherInterfaceStateMachine sm : mNotifyList) {
|
||||
sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED, ifaces);
|
||||
for (IpServer ipServer : mNotifyList) {
|
||||
ipServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifaces);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1420,13 +1419,13 @@ public class Tethering extends BaseNetworkObserver {
|
||||
mOffload.updateUpstreamNetworkState(ns);
|
||||
}
|
||||
|
||||
private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) {
|
||||
private void handleInterfaceServingStateActive(int mode, IpServer who) {
|
||||
if (mNotifyList.indexOf(who) < 0) {
|
||||
mNotifyList.add(who);
|
||||
mIPv6TetheringCoordinator.addActiveDownstream(who, mode);
|
||||
}
|
||||
|
||||
if (mode == IControlsTethering.STATE_TETHERED) {
|
||||
if (mode == IpServer.STATE_TETHERED) {
|
||||
// No need to notify OffloadController just yet as there are no
|
||||
// "offload-able" prefixes to pass along. This will handled
|
||||
// when the TISM informs Tethering of its LinkProperties.
|
||||
@@ -1441,10 +1440,10 @@ public class Tethering extends BaseNetworkObserver {
|
||||
final WifiManager mgr = getWifiManager();
|
||||
final String iface = who.interfaceName();
|
||||
switch (mode) {
|
||||
case IControlsTethering.STATE_TETHERED:
|
||||
case IpServer.STATE_TETHERED:
|
||||
mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
|
||||
break;
|
||||
case IControlsTethering.STATE_LOCAL_ONLY:
|
||||
case IpServer.STATE_LOCAL_ONLY:
|
||||
mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
|
||||
break;
|
||||
default:
|
||||
@@ -1454,7 +1453,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) {
|
||||
private void handleInterfaceServingStateInactive(IpServer who) {
|
||||
mNotifyList.remove(who);
|
||||
mIPv6TetheringCoordinator.removeActiveDownstream(who);
|
||||
mOffload.excludeDownstreamInterface(who.interfaceName());
|
||||
@@ -1563,10 +1562,10 @@ public class Tethering extends BaseNetworkObserver {
|
||||
boolean retValue = true;
|
||||
switch (message.what) {
|
||||
case EVENT_IFACE_SERVING_STATE_ACTIVE: {
|
||||
TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
|
||||
IpServer who = (IpServer) message.obj;
|
||||
if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
|
||||
handleInterfaceServingStateActive(message.arg1, who);
|
||||
who.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
|
||||
who.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED,
|
||||
mCurrentUpstreamIfaceSet);
|
||||
// If there has been a change and an upstream is now
|
||||
// desired, kick off the selection process.
|
||||
@@ -1577,7 +1576,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
break;
|
||||
}
|
||||
case EVENT_IFACE_SERVING_STATE_INACTIVE: {
|
||||
TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
|
||||
IpServer who = (IpServer) message.obj;
|
||||
if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
|
||||
handleInterfaceServingStateInactive(who);
|
||||
|
||||
@@ -1591,7 +1590,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
if (DBG) {
|
||||
Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
|
||||
" live requests:");
|
||||
for (TetherInterfaceStateMachine o : mNotifyList) {
|
||||
for (IpServer o : mNotifyList) {
|
||||
Log.d(TAG, " " + o);
|
||||
}
|
||||
}
|
||||
@@ -1605,7 +1604,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
case EVENT_IFACE_UPDATE_LINKPROPERTIES: {
|
||||
final LinkProperties newLp = (LinkProperties) message.obj;
|
||||
if (message.arg1 == IControlsTethering.STATE_TETHERED) {
|
||||
if (message.arg1 == IpServer.STATE_TETHERED) {
|
||||
mOffload.updateDownstreamLinkProperties(newLp);
|
||||
} else {
|
||||
mOffload.excludeDownstreamInterface(newLp.getInterfaceName());
|
||||
@@ -1650,7 +1649,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
boolean retValue = true;
|
||||
switch (message.what) {
|
||||
case EVENT_IFACE_SERVING_STATE_ACTIVE:
|
||||
TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
|
||||
IpServer who = (IpServer) message.obj;
|
||||
who.sendMessage(mErrorNotification);
|
||||
break;
|
||||
case CMD_CLEAR_ERROR:
|
||||
@@ -1665,8 +1664,8 @@ public class Tethering extends BaseNetworkObserver {
|
||||
|
||||
void notify(int msgType) {
|
||||
mErrorNotification = msgType;
|
||||
for (TetherInterfaceStateMachine sm : mNotifyList) {
|
||||
sm.sendMessage(msgType);
|
||||
for (IpServer ipServer : mNotifyList) {
|
||||
ipServer.sendMessage(msgType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1676,7 +1675,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
@Override
|
||||
public void enter() {
|
||||
Log.e(TAG, "Error in setIpForwardingEnabled");
|
||||
notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR);
|
||||
notify(IpServer.CMD_IP_FORWARDING_ENABLE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1684,7 +1683,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
@Override
|
||||
public void enter() {
|
||||
Log.e(TAG, "Error in setIpForwardingDisabled");
|
||||
notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR);
|
||||
notify(IpServer.CMD_IP_FORWARDING_DISABLE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1692,7 +1691,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
@Override
|
||||
public void enter() {
|
||||
Log.e(TAG, "Error in startTethering");
|
||||
notify(TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR);
|
||||
notify(IpServer.CMD_START_TETHERING_ERROR);
|
||||
try {
|
||||
mNMService.setIpForwardingEnabled(false);
|
||||
} catch (Exception e) {}
|
||||
@@ -1703,7 +1702,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
@Override
|
||||
public void enter() {
|
||||
Log.e(TAG, "Error in stopTethering");
|
||||
notify(TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR);
|
||||
notify(IpServer.CMD_STOP_TETHERING_ERROR);
|
||||
try {
|
||||
mNMService.setIpForwardingEnabled(false);
|
||||
} catch (Exception e) {}
|
||||
@@ -1714,7 +1713,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
@Override
|
||||
public void enter() {
|
||||
Log.e(TAG, "Error in setDnsForwarders");
|
||||
notify(TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR);
|
||||
notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR);
|
||||
try {
|
||||
mNMService.stopTethering();
|
||||
} catch (Exception e) {}
|
||||
@@ -1771,15 +1770,15 @@ public class Tethering extends BaseNetworkObserver {
|
||||
|
||||
// Maybe add prefixes or addresses for downstreams, depending on
|
||||
// the IP serving mode of each.
|
||||
for (TetherInterfaceStateMachine tism : mNotifyList) {
|
||||
final LinkProperties lp = tism.linkProperties();
|
||||
for (IpServer ipServer : mNotifyList) {
|
||||
final LinkProperties lp = ipServer.linkProperties();
|
||||
|
||||
switch (tism.servingMode()) {
|
||||
case IControlsTethering.STATE_UNAVAILABLE:
|
||||
case IControlsTethering.STATE_AVAILABLE:
|
||||
switch (ipServer.servingMode()) {
|
||||
case IpServer.STATE_UNAVAILABLE:
|
||||
case IpServer.STATE_AVAILABLE:
|
||||
// No usable LinkProperties in these states.
|
||||
continue;
|
||||
case IControlsTethering.STATE_TETHERED:
|
||||
case IpServer.STATE_TETHERED:
|
||||
// Only add IPv4 /32 and IPv6 /128 prefixes. The
|
||||
// directly-connected prefixes will be sent as
|
||||
// downstream "offload-able" prefixes.
|
||||
@@ -1789,7 +1788,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
localPrefixes.add(PrefixUtils.ipAddressAsPrefix(ip));
|
||||
}
|
||||
break;
|
||||
case IControlsTethering.STATE_LOCAL_ONLY:
|
||||
case IpServer.STATE_LOCAL_ONLY:
|
||||
// Add prefixes covering all local IPs.
|
||||
localPrefixes.addAll(PrefixUtils.localPrefixesFrom(lp));
|
||||
break;
|
||||
@@ -1826,16 +1825,16 @@ public class Tethering extends BaseNetworkObserver {
|
||||
pw.print(iface + " - ");
|
||||
|
||||
switch (tetherState.lastState) {
|
||||
case IControlsTethering.STATE_UNAVAILABLE:
|
||||
case IpServer.STATE_UNAVAILABLE:
|
||||
pw.print("UnavailableState");
|
||||
break;
|
||||
case IControlsTethering.STATE_AVAILABLE:
|
||||
case IpServer.STATE_AVAILABLE:
|
||||
pw.print("AvailableState");
|
||||
break;
|
||||
case IControlsTethering.STATE_TETHERED:
|
||||
case IpServer.STATE_TETHERED:
|
||||
pw.print("TetheredState");
|
||||
break;
|
||||
case IControlsTethering.STATE_LOCAL_ONLY:
|
||||
case IpServer.STATE_LOCAL_ONLY:
|
||||
pw.print("LocalHotspotState");
|
||||
break;
|
||||
default:
|
||||
@@ -1873,28 +1872,26 @@ public class Tethering extends BaseNetworkObserver {
|
||||
return false;
|
||||
}
|
||||
|
||||
private IControlsTethering makeControlCallback(String ifname) {
|
||||
return new IControlsTethering() {
|
||||
private IpServer.Callback makeControlCallback() {
|
||||
return new IpServer.Callback() {
|
||||
@Override
|
||||
public void updateInterfaceState(
|
||||
TetherInterfaceStateMachine who, int state, int lastError) {
|
||||
notifyInterfaceStateChange(ifname, who, state, lastError);
|
||||
public void updateInterfaceState(IpServer who, int state, int lastError) {
|
||||
notifyInterfaceStateChange(who, state, lastError);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLinkProperties(
|
||||
TetherInterfaceStateMachine who, LinkProperties newLp) {
|
||||
notifyLinkPropertiesChanged(ifname, who, newLp);
|
||||
public void updateLinkProperties(IpServer who, LinkProperties newLp) {
|
||||
notifyLinkPropertiesChanged(who, newLp);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Move into TetherMasterSM.
|
||||
private void notifyInterfaceStateChange(
|
||||
String iface, TetherInterfaceStateMachine who, int state, int error) {
|
||||
private void notifyInterfaceStateChange(IpServer who, int state, int error) {
|
||||
final String iface = who.interfaceName();
|
||||
synchronized (mPublicSync) {
|
||||
final TetherState tetherState = mTetherStates.get(iface);
|
||||
if (tetherState != null && tetherState.stateMachine.equals(who)) {
|
||||
if (tetherState != null && tetherState.ipServer.equals(who)) {
|
||||
tetherState.lastState = state;
|
||||
tetherState.lastError = error;
|
||||
} else {
|
||||
@@ -1908,7 +1905,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
// Notify that we're tethering (or not) this interface.
|
||||
// This is how data saver for instance knows if the user explicitly
|
||||
// turned on tethering (thus keeping us from being in data saver mode).
|
||||
mPolicyManager.onTetheringChanged(iface, state == IControlsTethering.STATE_TETHERED);
|
||||
mPolicyManager.onTetheringChanged(iface, state == IpServer.STATE_TETHERED);
|
||||
} catch (RemoteException e) {
|
||||
// Not really very much we can do here.
|
||||
}
|
||||
@@ -1921,12 +1918,12 @@ public class Tethering extends BaseNetworkObserver {
|
||||
}
|
||||
int which;
|
||||
switch (state) {
|
||||
case IControlsTethering.STATE_UNAVAILABLE:
|
||||
case IControlsTethering.STATE_AVAILABLE:
|
||||
case IpServer.STATE_UNAVAILABLE:
|
||||
case IpServer.STATE_AVAILABLE:
|
||||
which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
|
||||
break;
|
||||
case IControlsTethering.STATE_TETHERED:
|
||||
case IControlsTethering.STATE_LOCAL_ONLY:
|
||||
case IpServer.STATE_TETHERED:
|
||||
case IpServer.STATE_LOCAL_ONLY:
|
||||
which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
|
||||
break;
|
||||
default:
|
||||
@@ -1937,12 +1934,12 @@ public class Tethering extends BaseNetworkObserver {
|
||||
sendTetherStateChangedBroadcast();
|
||||
}
|
||||
|
||||
private void notifyLinkPropertiesChanged(String iface, TetherInterfaceStateMachine who,
|
||||
LinkProperties newLp) {
|
||||
private void notifyLinkPropertiesChanged(IpServer who, LinkProperties newLp) {
|
||||
final String iface = who.interfaceName();
|
||||
final int state;
|
||||
synchronized (mPublicSync) {
|
||||
final TetherState tetherState = mTetherStates.get(iface);
|
||||
if (tetherState != null && tetherState.stateMachine.equals(who)) {
|
||||
if (tetherState != null && tetherState.ipServer.equals(who)) {
|
||||
state = tetherState.lastState;
|
||||
} else {
|
||||
mLog.log("got notification from stale iface " + iface);
|
||||
@@ -1952,7 +1949,7 @@ public class Tethering extends BaseNetworkObserver {
|
||||
|
||||
mLog.log(String.format(
|
||||
"OBSERVED LinkProperties update iface=%s state=%s lp=%s",
|
||||
iface, IControlsTethering.getStateString(state), newLp));
|
||||
iface, IpServer.getStateString(state), newLp));
|
||||
final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
|
||||
mTetherMasterSM.sendMessage(which, state, 0, newLp);
|
||||
}
|
||||
@@ -1976,11 +1973,11 @@ public class Tethering extends BaseNetworkObserver {
|
||||
|
||||
mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
|
||||
final TetherState tetherState = new TetherState(
|
||||
new TetherInterfaceStateMachine(
|
||||
iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
|
||||
makeControlCallback(iface), mConfig.enableLegacyDhcpServer, mDeps));
|
||||
new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
|
||||
makeControlCallback(), mConfig.enableLegacyDhcpServer,
|
||||
mDeps.getIpServerDependencies()));
|
||||
mTetherStates.put(iface, tetherState);
|
||||
tetherState.stateMachine.start();
|
||||
tetherState.ipServer.start();
|
||||
}
|
||||
|
||||
private void stopTrackingInterfaceLocked(final String iface) {
|
||||
@@ -1989,36 +1986,11 @@ public class Tethering extends BaseNetworkObserver {
|
||||
mLog.log("attempting to remove unknown iface (" + iface + "), ignoring");
|
||||
return;
|
||||
}
|
||||
tetherState.stateMachine.stop();
|
||||
tetherState.ipServer.stop();
|
||||
mLog.log("removing TetheringInterfaceStateMachine for: " + iface);
|
||||
mTetherStates.remove(iface);
|
||||
}
|
||||
|
||||
private static String getIPv4DefaultRouteInterface(NetworkState ns) {
|
||||
if (ns == null) return null;
|
||||
return getInterfaceForDestination(ns.linkProperties, Inet4Address.ANY);
|
||||
}
|
||||
|
||||
private static String getIPv6DefaultRouteInterface(NetworkState ns) {
|
||||
if (ns == null) return null;
|
||||
// An upstream network's IPv6 capability is currently only useful if it
|
||||
// can be 64share'd downstream (RFC 7278). For now, that means mobile
|
||||
// upstream networks only.
|
||||
if (ns.networkCapabilities == null ||
|
||||
!ns.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getInterfaceForDestination(ns.linkProperties, Inet6Address.ANY);
|
||||
}
|
||||
|
||||
private static String getInterfaceForDestination(LinkProperties lp, InetAddress dst) {
|
||||
final RouteInfo ri = (lp != null)
|
||||
? RouteInfo.selectBestRoute(lp.getAllRoutes(), dst)
|
||||
: null;
|
||||
return (ri != null) ? ri.getInterface() : null;
|
||||
}
|
||||
|
||||
private static String[] copy(String[] strarray) {
|
||||
return Arrays.copyOf(strarray, strarray.length);
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
import android.net.LinkProperties;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*
|
||||
* Interface with methods necessary to notify that a given interface is ready for tethering.
|
||||
*
|
||||
* Rename to something more representative, e.g. IpServingControlCallback.
|
||||
*
|
||||
* All methods MUST be called on the TetherMasterSM main Looper's thread.
|
||||
*/
|
||||
public class IControlsTethering {
|
||||
public static final int STATE_UNAVAILABLE = 0;
|
||||
public static final int STATE_AVAILABLE = 1;
|
||||
public static final int STATE_TETHERED = 2;
|
||||
public static final int STATE_LOCAL_ONLY = 3;
|
||||
|
||||
public static String getStateString(int state) {
|
||||
switch (state) {
|
||||
case STATE_UNAVAILABLE: return "UNAVAILABLE";
|
||||
case STATE_AVAILABLE: return "AVAILABLE";
|
||||
case STATE_TETHERED: return "TETHERED";
|
||||
case STATE_LOCAL_ONLY: return "LOCAL_ONLY";
|
||||
}
|
||||
return "UNKNOWN: " + state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify that |who| has changed its tethering state.
|
||||
*
|
||||
* TODO: Remove the need for the |who| argument.
|
||||
*
|
||||
* @param who corresponding instance of a TetherInterfaceStateMachine
|
||||
* @param state one of IControlsTethering.STATE_*
|
||||
* @param lastError one of ConnectivityManager.TETHER_ERROR_*
|
||||
*/
|
||||
public void updateInterfaceState(TetherInterfaceStateMachine who, int state, int lastError) {}
|
||||
|
||||
/**
|
||||
* Notify that |who| has new LinkProperties.
|
||||
*
|
||||
* TODO: Remove the need for the |who| argument.
|
||||
*
|
||||
* @param who corresponding instance of a TetherInterfaceStateMachine
|
||||
* @param newLp the new LinkProperties to report
|
||||
*/
|
||||
public void updateLinkProperties(TetherInterfaceStateMachine who, LinkProperties newLp) {}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ip.IpServer;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
@@ -50,19 +51,19 @@ public class IPv6TetheringCoordinator {
|
||||
private static final boolean VDBG = false;
|
||||
|
||||
private static class Downstream {
|
||||
public final TetherInterfaceStateMachine tism;
|
||||
public final int mode; // IControlsTethering.STATE_*
|
||||
public final IpServer ipServer;
|
||||
public final int mode; // IpServer.STATE_*
|
||||
// Used to append to a ULA /48, constructing a ULA /64 for local use.
|
||||
public final short subnetId;
|
||||
|
||||
Downstream(TetherInterfaceStateMachine tism, int mode, short subnetId) {
|
||||
this.tism = tism;
|
||||
Downstream(IpServer ipServer, int mode, short subnetId) {
|
||||
this.ipServer = ipServer;
|
||||
this.mode = mode;
|
||||
this.subnetId = subnetId;
|
||||
}
|
||||
}
|
||||
|
||||
private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
|
||||
private final ArrayList<IpServer> mNotifyList;
|
||||
private final SharedLog mLog;
|
||||
// NOTE: mActiveDownstreams is a list and not a hash data structure because
|
||||
// we keep active downstreams in arrival order. This is done so /64s can
|
||||
@@ -74,8 +75,7 @@ public class IPv6TetheringCoordinator {
|
||||
private short mNextSubnetId;
|
||||
private NetworkState mUpstreamNetworkState;
|
||||
|
||||
public IPv6TetheringCoordinator(ArrayList<TetherInterfaceStateMachine> notifyList,
|
||||
SharedLog log) {
|
||||
public IPv6TetheringCoordinator(ArrayList<IpServer> notifyList, SharedLog log) {
|
||||
mNotifyList = notifyList;
|
||||
mLog = log.forSubComponent(TAG);
|
||||
mActiveDownstreams = new LinkedList<>();
|
||||
@@ -83,7 +83,7 @@ public class IPv6TetheringCoordinator {
|
||||
mNextSubnetId = 0;
|
||||
}
|
||||
|
||||
public void addActiveDownstream(TetherInterfaceStateMachine downstream, int mode) {
|
||||
public void addActiveDownstream(IpServer downstream, int mode) {
|
||||
if (findDownstream(downstream) == null) {
|
||||
// Adding a new downstream appends it to the list. Adding a
|
||||
// downstream a second time without first removing it has no effect.
|
||||
@@ -98,7 +98,7 @@ public class IPv6TetheringCoordinator {
|
||||
}
|
||||
}
|
||||
|
||||
public void removeActiveDownstream(TetherInterfaceStateMachine downstream) {
|
||||
public void removeActiveDownstream(IpServer downstream) {
|
||||
stopIPv6TetheringOn(downstream);
|
||||
if (mActiveDownstreams.remove(findDownstream(downstream))) {
|
||||
updateIPv6TetheringInterfaces();
|
||||
@@ -133,8 +133,8 @@ public class IPv6TetheringCoordinator {
|
||||
}
|
||||
|
||||
private void stopIPv6TetheringOnAllInterfaces() {
|
||||
for (TetherInterfaceStateMachine sm : mNotifyList) {
|
||||
stopIPv6TetheringOn(sm);
|
||||
for (IpServer ipServer : mNotifyList) {
|
||||
stopIPv6TetheringOn(ipServer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,28 +156,28 @@ public class IPv6TetheringCoordinator {
|
||||
}
|
||||
|
||||
private void updateIPv6TetheringInterfaces() {
|
||||
for (TetherInterfaceStateMachine sm : mNotifyList) {
|
||||
final LinkProperties lp = getInterfaceIPv6LinkProperties(sm);
|
||||
sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, lp);
|
||||
for (IpServer ipServer : mNotifyList) {
|
||||
final LinkProperties lp = getInterfaceIPv6LinkProperties(ipServer);
|
||||
ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, lp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private LinkProperties getInterfaceIPv6LinkProperties(TetherInterfaceStateMachine sm) {
|
||||
if (sm.interfaceType() == ConnectivityManager.TETHERING_BLUETOOTH) {
|
||||
private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) {
|
||||
if (ipServer.interfaceType() == ConnectivityManager.TETHERING_BLUETOOTH) {
|
||||
// TODO: Figure out IPv6 support on PAN interfaces.
|
||||
return null;
|
||||
}
|
||||
|
||||
final Downstream ds = findDownstream(sm);
|
||||
final Downstream ds = findDownstream(ipServer);
|
||||
if (ds == null) return null;
|
||||
|
||||
if (ds.mode == IControlsTethering.STATE_LOCAL_ONLY) {
|
||||
if (ds.mode == IpServer.STATE_LOCAL_ONLY) {
|
||||
// Build a Unique Locally-assigned Prefix configuration.
|
||||
return getUniqueLocalConfig(mUniqueLocalPrefix, ds.subnetId);
|
||||
}
|
||||
|
||||
// This downstream is in IControlsTethering.STATE_TETHERED mode.
|
||||
// This downstream is in IpServer.STATE_TETHERED mode.
|
||||
if (mUpstreamNetworkState == null || mUpstreamNetworkState.linkProperties == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ public class IPv6TetheringCoordinator {
|
||||
// IPv6 toward the oldest (first requested) active downstream.
|
||||
|
||||
final Downstream currentActive = mActiveDownstreams.peek();
|
||||
if (currentActive != null && currentActive.tism == sm) {
|
||||
if (currentActive != null && currentActive.ipServer == ipServer) {
|
||||
final LinkProperties lp = getIPv6OnlyLinkProperties(
|
||||
mUpstreamNetworkState.linkProperties);
|
||||
if (lp.hasIPv6DefaultRoute() && lp.hasGlobalIPv6Address()) {
|
||||
@@ -199,9 +199,9 @@ public class IPv6TetheringCoordinator {
|
||||
return null;
|
||||
}
|
||||
|
||||
Downstream findDownstream(TetherInterfaceStateMachine tism) {
|
||||
Downstream findDownstream(IpServer ipServer) {
|
||||
for (Downstream ds : mActiveDownstreams) {
|
||||
if (ds.tism == tism) return ds;
|
||||
if (ds.ipServer == ipServer) return ds;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -304,7 +304,7 @@ public class IPv6TetheringCoordinator {
|
||||
ns.linkProperties);
|
||||
}
|
||||
|
||||
private static void stopIPv6TetheringOn(TetherInterfaceStateMachine sm) {
|
||||
sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
|
||||
private static void stopIPv6TetheringOn(IpServer ipServer) {
|
||||
ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.net.INetd;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.dhcp.DhcpServer;
|
||||
import android.net.dhcp.DhcpServingParams;
|
||||
import android.net.ip.IpServer;
|
||||
import android.net.ip.RouterAdvertisementDaemon;
|
||||
import android.net.util.InterfaceParams;
|
||||
import android.net.util.NetdService;
|
||||
@@ -49,20 +50,12 @@ public class TetheringDependencies {
|
||||
}
|
||||
|
||||
public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
|
||||
ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) {
|
||||
ArrayList<IpServer> notifyList, SharedLog log) {
|
||||
return new IPv6TetheringCoordinator(notifyList, log);
|
||||
}
|
||||
|
||||
public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
|
||||
return new RouterAdvertisementDaemon(ifParams);
|
||||
}
|
||||
|
||||
public InterfaceParams getInterfaceParams(String ifName) {
|
||||
return InterfaceParams.getByName(ifName);
|
||||
}
|
||||
|
||||
public INetd getNetdService() {
|
||||
return NetdService.getInstance();
|
||||
public IpServer.Dependencies getIpServerDependencies() {
|
||||
return new IpServer.Dependencies();
|
||||
}
|
||||
|
||||
public boolean isTetheringSupported() {
|
||||
@@ -72,9 +65,4 @@ public class TetheringDependencies {
|
||||
public NetworkRequest getDefaultNetworkRequest() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public DhcpServer makeDhcpServer(Looper looper, InterfaceParams iface, DhcpServingParams params,
|
||||
SharedLog log) {
|
||||
return new DhcpServer(looper, iface, params, log);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.connectivity.tethering;
|
||||
package android.net.ip;
|
||||
|
||||
import static android.net.NetworkUtils.numericToInetAddress;
|
||||
import static android.net.util.NetworkConstants.asByte;
|
||||
@@ -31,11 +31,10 @@ import android.net.LinkProperties;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.dhcp.DhcpServer;
|
||||
import android.net.dhcp.DhcpServingParams;
|
||||
import android.net.ip.InterfaceController;
|
||||
import android.net.ip.RouterAdvertisementDaemon;
|
||||
import android.net.ip.RouterAdvertisementDaemon.RaParams;
|
||||
import android.net.util.InterfaceParams;
|
||||
import android.net.util.InterfaceSet;
|
||||
import android.net.util.NetdService;
|
||||
import android.net.util.SharedLog;
|
||||
import android.os.INetworkManagementService;
|
||||
import android.os.Looper;
|
||||
@@ -67,7 +66,22 @@ import java.util.Set;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class TetherInterfaceStateMachine extends StateMachine {
|
||||
public class IpServer extends StateMachine {
|
||||
public static final int STATE_UNAVAILABLE = 0;
|
||||
public static final int STATE_AVAILABLE = 1;
|
||||
public static final int STATE_TETHERED = 2;
|
||||
public static final int STATE_LOCAL_ONLY = 3;
|
||||
|
||||
public static String getStateString(int state) {
|
||||
switch (state) {
|
||||
case STATE_UNAVAILABLE: return "UNAVAILABLE";
|
||||
case STATE_AVAILABLE: return "AVAILABLE";
|
||||
case STATE_TETHERED: return "TETHERED";
|
||||
case STATE_LOCAL_ONLY: return "LOCAL_ONLY";
|
||||
}
|
||||
return "UNKNOWN: " + state;
|
||||
}
|
||||
|
||||
private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
|
||||
private static final byte DOUG_ADAMS = (byte) 42;
|
||||
|
||||
@@ -83,15 +97,53 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
// TODO: have this configurable
|
||||
private static final int DHCP_LEASE_TIME_SECS = 3600;
|
||||
|
||||
private final static String TAG = "TetherInterfaceSM";
|
||||
private final static String TAG = "IpServer";
|
||||
private final static boolean DBG = false;
|
||||
private final static boolean VDBG = false;
|
||||
private static final Class[] messageClasses = {
|
||||
TetherInterfaceStateMachine.class
|
||||
IpServer.class
|
||||
};
|
||||
private static final SparseArray<String> sMagicDecoderRing =
|
||||
MessageUtils.findMessageNames(messageClasses);
|
||||
|
||||
public static class Callback {
|
||||
/**
|
||||
* Notify that |who| has changed its tethering state.
|
||||
*
|
||||
* @param who the calling instance of IpServer
|
||||
* @param state one of STATE_*
|
||||
* @param lastError one of ConnectivityManager.TETHER_ERROR_*
|
||||
*/
|
||||
public void updateInterfaceState(IpServer who, int state, int lastError) {}
|
||||
|
||||
/**
|
||||
* Notify that |who| has new LinkProperties.
|
||||
*
|
||||
* @param who the calling instance of IpServer
|
||||
* @param newLp the new LinkProperties to report
|
||||
*/
|
||||
public void updateLinkProperties(IpServer who, LinkProperties newLp) {}
|
||||
}
|
||||
|
||||
public static class Dependencies {
|
||||
public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
|
||||
return new RouterAdvertisementDaemon(ifParams);
|
||||
}
|
||||
|
||||
public InterfaceParams getInterfaceParams(String ifName) {
|
||||
return InterfaceParams.getByName(ifName);
|
||||
}
|
||||
|
||||
public INetd getNetdService() {
|
||||
return NetdService.getInstance();
|
||||
}
|
||||
|
||||
public DhcpServer makeDhcpServer(Looper looper, InterfaceParams iface,
|
||||
DhcpServingParams params, SharedLog log) {
|
||||
return new DhcpServer(looper, iface, params, log);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100;
|
||||
// request from the user that it wants to tether
|
||||
public static final int CMD_TETHER_REQUESTED = BASE_IFACE + 2;
|
||||
@@ -123,7 +175,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
private final INetworkManagementService mNMService;
|
||||
private final INetd mNetd;
|
||||
private final INetworkStatsService mStatsService;
|
||||
private final IControlsTethering mTetherController;
|
||||
private final Callback mCallback;
|
||||
private final InterfaceController mInterfaceCtrl;
|
||||
|
||||
private final String mIfaceName;
|
||||
@@ -131,7 +183,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
private final LinkProperties mLinkProperties;
|
||||
private final boolean mUsingLegacyDhcp;
|
||||
|
||||
private final TetheringDependencies mDeps;
|
||||
private final Dependencies mDeps;
|
||||
|
||||
private int mLastError;
|
||||
private int mServingMode;
|
||||
@@ -148,17 +200,16 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
private DhcpServer mDhcpServer;
|
||||
private RaParams mLastRaParams;
|
||||
|
||||
public TetherInterfaceStateMachine(
|
||||
public IpServer(
|
||||
String ifaceName, Looper looper, int interfaceType, SharedLog log,
|
||||
INetworkManagementService nMService, INetworkStatsService statsService,
|
||||
IControlsTethering tetherController, boolean usingLegacyDhcp,
|
||||
TetheringDependencies deps) {
|
||||
Callback callback, boolean usingLegacyDhcp, Dependencies deps) {
|
||||
super(ifaceName, looper);
|
||||
mLog = log.forSubComponent(ifaceName);
|
||||
mNMService = nMService;
|
||||
mNetd = deps.getNetdService();
|
||||
mStatsService = statsService;
|
||||
mTetherController = tetherController;
|
||||
mCallback = callback;
|
||||
mInterfaceCtrl = new InterfaceController(ifaceName, nMService, mNetd, mLog);
|
||||
mIfaceName = ifaceName;
|
||||
mInterfaceType = interfaceType;
|
||||
@@ -167,7 +218,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
mDeps = deps;
|
||||
resetLinkProperties();
|
||||
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||
mServingMode = IControlsTethering.STATE_AVAILABLE;
|
||||
mServingMode = STATE_AVAILABLE;
|
||||
|
||||
mInitialState = new InitialState();
|
||||
mLocalHotspotState = new LocalHotspotState();
|
||||
@@ -521,14 +572,12 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
|
||||
private void sendInterfaceState(int newInterfaceState) {
|
||||
mServingMode = newInterfaceState;
|
||||
mTetherController.updateInterfaceState(
|
||||
TetherInterfaceStateMachine.this, newInterfaceState, mLastError);
|
||||
mCallback.updateInterfaceState(this, newInterfaceState, mLastError);
|
||||
sendLinkProperties();
|
||||
}
|
||||
|
||||
private void sendLinkProperties() {
|
||||
mTetherController.updateLinkProperties(
|
||||
TetherInterfaceStateMachine.this, new LinkProperties(mLinkProperties));
|
||||
mCallback.updateLinkProperties(this, new LinkProperties(mLinkProperties));
|
||||
}
|
||||
|
||||
private void resetLinkProperties() {
|
||||
@@ -539,7 +588,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
class InitialState extends State {
|
||||
@Override
|
||||
public void enter() {
|
||||
sendInterfaceState(IControlsTethering.STATE_AVAILABLE);
|
||||
sendInterfaceState(STATE_AVAILABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -549,10 +598,10 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
case CMD_TETHER_REQUESTED:
|
||||
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||
switch (message.arg1) {
|
||||
case IControlsTethering.STATE_LOCAL_ONLY:
|
||||
case STATE_LOCAL_ONLY:
|
||||
transitionTo(mLocalHotspotState);
|
||||
break;
|
||||
case IControlsTethering.STATE_TETHERED:
|
||||
case STATE_TETHERED:
|
||||
transitionTo(mTetheredState);
|
||||
break;
|
||||
default:
|
||||
@@ -649,7 +698,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
// problematic because transitioning during a multi-state jump yields
|
||||
// a Log.wtf(). Ultimately, there should be only one ServingState,
|
||||
// and forwarding and NAT rules should be handled by a coordinating
|
||||
// functional element outside of TetherInterfaceStateMachine.
|
||||
// functional element outside of IpServer.
|
||||
class LocalHotspotState extends BaseServingState {
|
||||
@Override
|
||||
public void enter() {
|
||||
@@ -659,7 +708,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
}
|
||||
|
||||
if (DBG) Log.d(TAG, "Local hotspot " + mIfaceName);
|
||||
sendInterfaceState(IControlsTethering.STATE_LOCAL_ONLY);
|
||||
sendInterfaceState(STATE_LOCAL_ONLY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -685,7 +734,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
// problematic because transitioning during a multi-state jump yields
|
||||
// a Log.wtf(). Ultimately, there should be only one ServingState,
|
||||
// and forwarding and NAT rules should be handled by a coordinating
|
||||
// functional element outside of TetherInterfaceStateMachine.
|
||||
// functional element outside of IpServer.
|
||||
class TetheredState extends BaseServingState {
|
||||
@Override
|
||||
public void enter() {
|
||||
@@ -695,7 +744,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
}
|
||||
|
||||
if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
|
||||
sendInterfaceState(IControlsTethering.STATE_TETHERED);
|
||||
sendInterfaceState(STATE_TETHERED);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -817,7 +866,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
@Override
|
||||
public void enter() {
|
||||
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||
sendInterfaceState(IControlsTethering.STATE_UNAVAILABLE);
|
||||
sendInterfaceState(STATE_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.connectivity.tethering;
|
||||
package android.net.ip;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -37,9 +37,9 @@ import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
|
||||
import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
|
||||
import static android.net.ConnectivityManager.TETHERING_USB;
|
||||
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
||||
import static com.android.server.connectivity.tethering.IControlsTethering.STATE_AVAILABLE;
|
||||
import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED;
|
||||
import static com.android.server.connectivity.tethering.IControlsTethering.STATE_UNAVAILABLE;
|
||||
import static android.net.ip.IpServer.STATE_AVAILABLE;
|
||||
import static android.net.ip.IpServer.STATE_TETHERED;
|
||||
import static android.net.ip.IpServer.STATE_UNAVAILABLE;
|
||||
|
||||
import android.net.INetworkStatsService;
|
||||
import android.net.InterfaceConfiguration;
|
||||
@@ -50,7 +50,6 @@ import android.net.MacAddress;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.dhcp.DhcpServer;
|
||||
import android.net.dhcp.DhcpServingParams;
|
||||
import android.net.ip.RouterAdvertisementDaemon;
|
||||
import android.net.util.InterfaceParams;
|
||||
import android.net.util.InterfaceSet;
|
||||
import android.net.util.SharedLog;
|
||||
@@ -74,7 +73,7 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class TetherInterfaceStateMachineTest {
|
||||
public class IpServerTest {
|
||||
private static final String IFACE_NAME = "testnet1";
|
||||
private static final String UPSTREAM_IFACE = "upstream0";
|
||||
private static final String UPSTREAM_IFACE2 = "upstream1";
|
||||
@@ -85,39 +84,38 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Mock private INetworkManagementService mNMService;
|
||||
@Mock private INetworkStatsService mStatsService;
|
||||
@Mock private IControlsTethering mTetherHelper;
|
||||
@Mock private IpServer.Callback mCallback;
|
||||
@Mock private InterfaceConfiguration mInterfaceConfiguration;
|
||||
@Mock private SharedLog mSharedLog;
|
||||
@Mock private DhcpServer mDhcpServer;
|
||||
@Mock private RouterAdvertisementDaemon mRaDaemon;
|
||||
@Mock private TetheringDependencies mTetheringDependencies;
|
||||
@Mock private IpServer.Dependencies mDependencies;
|
||||
|
||||
@Captor private ArgumentCaptor<DhcpServingParams> mDhcpParamsCaptor;
|
||||
|
||||
private final TestLooper mLooper = new TestLooper();
|
||||
private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
|
||||
ArgumentCaptor.forClass(LinkProperties.class);
|
||||
private TetherInterfaceStateMachine mTestedSm;
|
||||
private IpServer mIpServer;
|
||||
|
||||
private void initStateMachine(int interfaceType) throws Exception {
|
||||
initStateMachine(interfaceType, false /* usingLegacyDhcp */);
|
||||
}
|
||||
|
||||
private void initStateMachine(int interfaceType, boolean usingLegacyDhcp) throws Exception {
|
||||
mTestedSm = new TetherInterfaceStateMachine(
|
||||
mIpServer = new IpServer(
|
||||
IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog,
|
||||
mNMService, mStatsService, mTetherHelper, usingLegacyDhcp,
|
||||
mTetheringDependencies);
|
||||
mTestedSm.start();
|
||||
mNMService, mStatsService, mCallback, usingLegacyDhcp, mDependencies);
|
||||
mIpServer.start();
|
||||
// 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.
|
||||
mLooper.dispatchAll();
|
||||
reset(mNMService, mStatsService, mTetherHelper);
|
||||
reset(mNMService, mStatsService, mCallback);
|
||||
when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
|
||||
when(mTetheringDependencies.makeDhcpServer(
|
||||
when(mDependencies.makeDhcpServer(
|
||||
any(), any(), mDhcpParamsCaptor.capture(), any())).thenReturn(mDhcpServer);
|
||||
when(mTetheringDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
|
||||
when(mTetheringDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
|
||||
when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
|
||||
when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
|
||||
|
||||
when(mRaDaemon.start()).thenReturn(true);
|
||||
}
|
||||
@@ -130,11 +128,11 @@ public class TetherInterfaceStateMachineTest {
|
||||
private void initTetheredStateMachine(int interfaceType, String upstreamIface,
|
||||
boolean usingLegacyDhcp) throws Exception {
|
||||
initStateMachine(interfaceType, usingLegacyDhcp);
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
||||
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
||||
if (upstreamIface != null) {
|
||||
dispatchTetherConnectionChanged(upstreamIface);
|
||||
}
|
||||
reset(mNMService, mStatsService, mTetherHelper);
|
||||
reset(mNMService, mStatsService, mCallback);
|
||||
when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
|
||||
}
|
||||
|
||||
@@ -145,34 +143,34 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void startsOutAvailable() {
|
||||
mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
|
||||
TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mTetherHelper,
|
||||
false /* usingLegacyDhcp */, mTetheringDependencies);
|
||||
mTestedSm.start();
|
||||
mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(),
|
||||
TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mCallback,
|
||||
false /* usingLegacyDhcp */, mDependencies);
|
||||
mIpServer.start();
|
||||
mLooper.dispatchAll();
|
||||
verify(mTetherHelper).updateInterfaceState(
|
||||
mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
verify(mTetherHelper).updateLinkProperties(eq(mTestedSm), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mTetherHelper, mNMService, mStatsService);
|
||||
verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mCallback, mNMService, mStatsService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDoNothingUntilRequested() throws Exception {
|
||||
initStateMachine(TETHERING_BLUETOOTH);
|
||||
final int [] NOOP_COMMANDS = {
|
||||
TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED,
|
||||
TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR,
|
||||
TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR,
|
||||
TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR,
|
||||
TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR,
|
||||
TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR,
|
||||
TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED
|
||||
IpServer.CMD_TETHER_UNREQUESTED,
|
||||
IpServer.CMD_IP_FORWARDING_ENABLE_ERROR,
|
||||
IpServer.CMD_IP_FORWARDING_DISABLE_ERROR,
|
||||
IpServer.CMD_START_TETHERING_ERROR,
|
||||
IpServer.CMD_STOP_TETHERING_ERROR,
|
||||
IpServer.CMD_SET_DNS_FORWARDERS_ERROR,
|
||||
IpServer.CMD_TETHER_CONNECTION_CHANGED
|
||||
};
|
||||
for (int command : NOOP_COMMANDS) {
|
||||
// None of these commands should trigger us to request action from
|
||||
// the rest of the system.
|
||||
dispatchCommand(command);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,57 +178,57 @@ public class TetherInterfaceStateMachineTest {
|
||||
public void handlesImmediateInterfaceDown() throws Exception {
|
||||
initStateMachine(TETHERING_BLUETOOTH);
|
||||
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
|
||||
verify(mTetherHelper).updateInterfaceState(
|
||||
mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
verify(mTetherHelper).updateLinkProperties(eq(mTestedSm), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
|
||||
verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canBeTethered() throws Exception {
|
||||
initStateMachine(TETHERING_BLUETOOTH);
|
||||
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
||||
InOrder inOrder = inOrder(mTetherHelper, mNMService);
|
||||
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
||||
InOrder inOrder = inOrder(mCallback, mNMService);
|
||||
inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
|
||||
inOrder.verify(mTetherHelper).updateInterfaceState(
|
||||
mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mTetherHelper).updateLinkProperties(
|
||||
eq(mTestedSm), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mCallback).updateLinkProperties(
|
||||
eq(mIpServer), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canUnrequestTethering() throws Exception {
|
||||
initTetheredStateMachine(TETHERING_BLUETOOTH, null);
|
||||
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
|
||||
InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
|
||||
dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
|
||||
InOrder inOrder = inOrder(mNMService, mStatsService, mCallback);
|
||||
inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
|
||||
inOrder.verify(mNMService).setInterfaceConfig(eq(IFACE_NAME), any());
|
||||
inOrder.verify(mTetherHelper).updateInterfaceState(
|
||||
mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mTetherHelper).updateLinkProperties(
|
||||
eq(mTestedSm), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mCallback).updateLinkProperties(
|
||||
eq(mIpServer), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canBeTetheredAsUsb() throws Exception {
|
||||
initStateMachine(TETHERING_USB);
|
||||
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
||||
InOrder inOrder = inOrder(mTetherHelper, mNMService);
|
||||
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
||||
InOrder inOrder = inOrder(mCallback, mNMService);
|
||||
inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
|
||||
inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
|
||||
inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
|
||||
inOrder.verify(mTetherHelper).updateInterfaceState(
|
||||
mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mTetherHelper).updateLinkProperties(
|
||||
eq(mTestedSm), mLinkPropertiesCaptor.capture());
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mCallback).updateLinkProperties(
|
||||
eq(mIpServer), mLinkPropertiesCaptor.capture());
|
||||
assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -243,7 +241,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
InOrder inOrder = inOrder(mNMService);
|
||||
inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE);
|
||||
inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -257,7 +255,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
|
||||
inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
|
||||
inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -300,18 +298,18 @@ public class TetherInterfaceStateMachineTest {
|
||||
public void canUnrequestTetheringWithUpstream() throws Exception {
|
||||
initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
|
||||
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
|
||||
InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
|
||||
dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
|
||||
InOrder inOrder = inOrder(mNMService, mStatsService, mCallback);
|
||||
inOrder.verify(mStatsService).forceUpdate();
|
||||
inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
|
||||
inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
|
||||
inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
|
||||
inOrder.verify(mNMService).setInterfaceConfig(eq(IFACE_NAME), any());
|
||||
inOrder.verify(mTetherHelper).updateInterfaceState(
|
||||
mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mTetherHelper).updateLinkProperties(
|
||||
eq(mTestedSm), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mCallback).updateLinkProperties(
|
||||
eq(mIpServer), any(LinkProperties.class));
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -322,15 +320,15 @@ public class TetherInterfaceStateMachineTest {
|
||||
if (shouldThrow) {
|
||||
doThrow(RemoteException.class).when(mNMService).untetherInterface(IFACE_NAME);
|
||||
}
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
|
||||
InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
|
||||
dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
|
||||
InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
|
||||
usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
|
||||
usbTeardownOrder.verify(mNMService).setInterfaceConfig(
|
||||
IFACE_NAME, mInterfaceConfiguration);
|
||||
usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
|
||||
mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
|
||||
eq(mTestedSm), mLinkPropertiesCaptor.capture());
|
||||
usbTeardownOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
|
||||
usbTeardownOrder.verify(mCallback).updateLinkProperties(
|
||||
eq(mIpServer), mLinkPropertiesCaptor.capture());
|
||||
assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
|
||||
}
|
||||
}
|
||||
@@ -340,15 +338,15 @@ public class TetherInterfaceStateMachineTest {
|
||||
initStateMachine(TETHERING_USB);
|
||||
|
||||
doThrow(RemoteException.class).when(mNMService).tetherInterface(IFACE_NAME);
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
||||
InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
|
||||
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
|
||||
InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
|
||||
usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
|
||||
usbTeardownOrder.verify(mNMService).setInterfaceConfig(
|
||||
IFACE_NAME, mInterfaceConfiguration);
|
||||
usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
|
||||
mTestedSm, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
|
||||
usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
|
||||
eq(mTestedSm), mLinkPropertiesCaptor.capture());
|
||||
usbTeardownOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
|
||||
usbTeardownOrder.verify(mCallback).updateLinkProperties(
|
||||
eq(mIpServer), mLinkPropertiesCaptor.capture());
|
||||
assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
|
||||
}
|
||||
|
||||
@@ -358,13 +356,13 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
doThrow(RemoteException.class).when(mNMService).enableNat(anyString(), anyString());
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
|
||||
InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
|
||||
InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
|
||||
usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
|
||||
usbTeardownOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
|
||||
usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
|
||||
mTestedSm, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
|
||||
usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
|
||||
eq(mTestedSm), mLinkPropertiesCaptor.capture());
|
||||
usbTeardownOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
|
||||
usbTeardownOrder.verify(mCallback).updateLinkProperties(
|
||||
eq(mIpServer), mLinkPropertiesCaptor.capture());
|
||||
assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
|
||||
}
|
||||
|
||||
@@ -372,11 +370,11 @@ public class TetherInterfaceStateMachineTest {
|
||||
public void ignoresDuplicateUpstreamNotifications() throws Exception {
|
||||
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
|
||||
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,11 +399,11 @@ public class TetherInterfaceStateMachineTest {
|
||||
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */);
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
|
||||
|
||||
verify(mTetheringDependencies, never()).makeDhcpServer(any(), any(), any(), any());
|
||||
verify(mDependencies, never()).makeDhcpServer(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
private void assertDhcpStarted(IpPrefix expectedPrefix) {
|
||||
verify(mTetheringDependencies, times(1)).makeDhcpServer(
|
||||
verify(mDependencies, times(1)).makeDhcpServer(
|
||||
eq(mLooper.getLooper()), eq(TEST_IFACE_PARAMS), any(), eq(mSharedLog));
|
||||
verify(mDhcpServer, times(1)).start();
|
||||
final DhcpServingParams params = mDhcpParamsCaptor.getValue();
|
||||
@@ -422,21 +420,21 @@ public class TetherInterfaceStateMachineTest {
|
||||
/**
|
||||
* Send a command to the state machine under test, and run the event loop to idle.
|
||||
*
|
||||
* @param command One of the TetherInterfaceStateMachine.CMD_* constants.
|
||||
* @param command One of the IpServer.CMD_* constants.
|
||||
* @param arg1 An additional argument to pass.
|
||||
*/
|
||||
private void dispatchCommand(int command, int arg1) {
|
||||
mTestedSm.sendMessage(command, arg1);
|
||||
mIpServer.sendMessage(command, arg1);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command to the state machine under test, and run the event loop to idle.
|
||||
*
|
||||
* @param command One of the TetherInterfaceStateMachine.CMD_* constants.
|
||||
* @param command One of the IpServer.CMD_* constants.
|
||||
*/
|
||||
private void dispatchCommand(int command) {
|
||||
mTestedSm.sendMessage(command);
|
||||
mIpServer.sendMessage(command);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
@@ -447,7 +445,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
* @param upstreamIface String name of upstream interface (or null)
|
||||
*/
|
||||
private void dispatchTetherConnectionChanged(String upstreamIface) {
|
||||
mTestedSm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
|
||||
mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED,
|
||||
new InterfaceSet(upstreamIface));
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
@@ -75,6 +75,7 @@ import android.net.NetworkRequest;
|
||||
import android.net.NetworkState;
|
||||
import android.net.NetworkUtils;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.ip.IpServer;
|
||||
import android.net.ip.RouterAdvertisementDaemon;
|
||||
import android.net.util.InterfaceParams;
|
||||
import android.net.util.NetworkConstants;
|
||||
@@ -99,10 +100,8 @@ import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.internal.util.test.BroadcastInterceptingContext;
|
||||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
import com.android.server.connectivity.tethering.IControlsTethering;
|
||||
import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
|
||||
import com.android.server.connectivity.tethering.OffloadHardwareInterface;
|
||||
import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
|
||||
import com.android.server.connectivity.tethering.TetheringDependencies;
|
||||
import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
|
||||
|
||||
@@ -190,7 +189,7 @@ public class TetheringTest {
|
||||
|
||||
public class MockTetheringDependencies extends TetheringDependencies {
|
||||
StateMachine upstreamNetworkMonitorMasterSM;
|
||||
ArrayList<TetherInterfaceStateMachine> ipv6CoordinatorNotifyList;
|
||||
ArrayList<IpServer> ipv6CoordinatorNotifyList;
|
||||
int isTetheringSupportedCalls;
|
||||
|
||||
public void reset() {
|
||||
@@ -213,29 +212,35 @@ public class TetheringTest {
|
||||
|
||||
@Override
|
||||
public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
|
||||
ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) {
|
||||
ArrayList<IpServer> notifyList, SharedLog log) {
|
||||
ipv6CoordinatorNotifyList = notifyList;
|
||||
return mIPv6TetheringCoordinator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
|
||||
return mRouterAdvertisementDaemon;
|
||||
}
|
||||
public IpServer.Dependencies getIpServerDependencies() {
|
||||
return new IpServer.Dependencies() {
|
||||
@Override
|
||||
public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
|
||||
InterfaceParams ifParams) {
|
||||
return mRouterAdvertisementDaemon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public INetd getNetdService() {
|
||||
return mNetd;
|
||||
}
|
||||
@Override
|
||||
public InterfaceParams getInterfaceParams(String ifName) {
|
||||
final String[] ifaces = new String[] {
|
||||
TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
|
||||
final int index = ArrayUtils.indexOf(ifaces, ifName);
|
||||
assertTrue("Non-mocked interface: " + ifName, index >= 0);
|
||||
return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
|
||||
MacAddress.ALL_ZEROS_ADDRESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InterfaceParams getInterfaceParams(String ifName) {
|
||||
final String[] ifaces = new String[] { TEST_USB_IFNAME, TEST_WLAN_IFNAME,
|
||||
TEST_MOBILE_IFNAME };
|
||||
final int index = ArrayUtils.indexOf(ifaces, ifName);
|
||||
assertTrue("Non-mocked interface: " + ifName, index >= 0);
|
||||
return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
|
||||
MacAddress.ALL_ZEROS_ADDRESS);
|
||||
@Override
|
||||
public INetd getNetdService() {
|
||||
return mNetd;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -458,9 +463,9 @@ public class TetheringTest {
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
// If, and only if, Tethering received an interface status changed
|
||||
// then it creates a TetherInterfaceStateMachine and sends out a
|
||||
// broadcast indicating that the interface is "available".
|
||||
// If, and only if, Tethering received an interface status changed then
|
||||
// it creates a IpServer and sends out a broadcast indicating that the
|
||||
// interface is "available".
|
||||
if (emulateInterfaceStatusChanged) {
|
||||
assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
|
||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||
@@ -557,18 +562,18 @@ public class TetheringTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send CMD_IPV6_TETHER_UPDATE to TISMs as would be done by IPv6TetheringCoordinator.
|
||||
* Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
|
||||
*/
|
||||
private void sendIPv6TetherUpdates(NetworkState upstreamState) {
|
||||
// IPv6TetheringCoordinator must have been notified of downstream
|
||||
verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
|
||||
argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
|
||||
eq(IControlsTethering.STATE_TETHERED));
|
||||
eq(IpServer.STATE_TETHERED));
|
||||
|
||||
for (TetherInterfaceStateMachine tism :
|
||||
for (IpServer ipSrv :
|
||||
mTetheringDependencies.ipv6CoordinatorNotifyList) {
|
||||
NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
|
||||
tism.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0,
|
||||
ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
|
||||
upstreamState.linkProperties.isIPv6Provisioned()
|
||||
? ipv6OnlyState.linkProperties
|
||||
: null);
|
||||
@@ -812,7 +817,7 @@ public class TetheringTest {
|
||||
|
||||
// We verify get/set called thrice here: once for setup and twice during
|
||||
// teardown because all events happen over the course of the single
|
||||
// dispatchAll() above. Note that once the TISM 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.
|
||||
verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
|
||||
verify(mNMService, times(3))
|
||||
|
||||
Reference in New Issue
Block a user