Tethering: Own WiFi tethering state and lifetime
- Add logic to Tethering to track whether the user has requested
tethering via WiFi.
- Subscribe to intents regarding soft AP state to enable and
disable tethering when the AP comes up or goes down.
- Refactor IP configuration logic to do configuration for WiFi
as well as USB.
Bug: 29054780
Test: WiFi tethering continues to work on angler
Tethering related unittests continue to pass.
Change-Id: I6eff2573ca3fd11fabcf138c468ba517ff2daf65
This commit is contained in:
@@ -128,7 +128,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
|
||||
private Map<String, TetherInterfaceStateMachine> mIfaces; // all tethered/tetherable ifaces
|
||||
|
||||
private BroadcastReceiver mStateReceiver;
|
||||
private final BroadcastReceiver mStateReceiver;
|
||||
|
||||
// {@link ComponentName} of the Service used to run tether provisioning.
|
||||
private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
|
||||
@@ -163,6 +163,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
private boolean mUsbTetherRequested; // true if USB tethering should be started
|
||||
// when RNDIS is enabled
|
||||
|
||||
// True iff WiFi tethering should be started when soft AP is ready.
|
||||
private boolean mWifiTetherRequested;
|
||||
|
||||
public Tethering(Context context, INetworkManagementService nmService,
|
||||
INetworkStatsService statsService) {
|
||||
mContext = context;
|
||||
@@ -184,6 +187,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(UsbManager.ACTION_USB_STATE);
|
||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
|
||||
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
|
||||
mContext.registerReceiver(mStateReceiver, filter);
|
||||
|
||||
@@ -245,29 +249,22 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
// Never called directly: only called from interfaceLinkStateChanged.
|
||||
// See NetlinkHandler.cpp:71.
|
||||
if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
|
||||
boolean found = false;
|
||||
boolean usb = false;
|
||||
synchronized (mPublicSync) {
|
||||
if (isWifi(iface)) {
|
||||
found = true;
|
||||
} else if (isUsb(iface)) {
|
||||
found = true;
|
||||
usb = true;
|
||||
} else if (isBluetooth(iface)) {
|
||||
found = true;
|
||||
int interfaceType = ifaceNameToType(iface);
|
||||
if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
|
||||
return;
|
||||
}
|
||||
if (found == false) return;
|
||||
|
||||
TetherInterfaceStateMachine sm = mIfaces.get(iface);
|
||||
if (up) {
|
||||
if (sm == null) {
|
||||
sm = new TetherInterfaceStateMachine(iface, mLooper, usb,
|
||||
sm = new TetherInterfaceStateMachine(iface, mLooper, interfaceType,
|
||||
mNMService, mStatsService, this);
|
||||
mIfaces.put(iface, sm);
|
||||
sm.start();
|
||||
}
|
||||
} else {
|
||||
if (isUsb(iface)) {
|
||||
if (interfaceType == ConnectivityManager.TETHERING_USB) {
|
||||
// ignore usb0 down after enabling RNDIS
|
||||
// we will handle disconnect in interfaceRemoved instead
|
||||
if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
|
||||
@@ -293,7 +290,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWifi(String iface) {
|
||||
private boolean isWifi(String iface) {
|
||||
synchronized (mPublicSync) {
|
||||
for (String regex : mTetherableWifiRegexs) {
|
||||
if (iface.matches(regex)) return true;
|
||||
@@ -302,7 +299,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBluetooth(String iface) {
|
||||
private boolean isBluetooth(String iface) {
|
||||
synchronized (mPublicSync) {
|
||||
for (String regex : mTetherableBluetoothRegexs) {
|
||||
if (iface.matches(regex)) return true;
|
||||
@@ -311,23 +308,23 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
}
|
||||
}
|
||||
|
||||
private int ifaceNameToType(String iface) {
|
||||
if (isWifi(iface)) {
|
||||
return ConnectivityManager.TETHERING_WIFI;
|
||||
} else if (isUsb(iface)) {
|
||||
return ConnectivityManager.TETHERING_USB;
|
||||
} else if (isBluetooth(iface)) {
|
||||
return ConnectivityManager.TETHERING_BLUETOOTH;
|
||||
}
|
||||
return ConnectivityManager.TETHERING_INVALID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interfaceAdded(String iface) {
|
||||
if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
|
||||
boolean found = false;
|
||||
boolean usb = false;
|
||||
synchronized (mPublicSync) {
|
||||
if (isWifi(iface)) {
|
||||
found = true;
|
||||
}
|
||||
if (isUsb(iface)) {
|
||||
found = true;
|
||||
usb = true;
|
||||
}
|
||||
if (isBluetooth(iface)) {
|
||||
found = true;
|
||||
}
|
||||
if (found == false) {
|
||||
int interfaceType = ifaceNameToType(iface);
|
||||
if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
|
||||
if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
|
||||
return;
|
||||
}
|
||||
@@ -337,7 +334,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
|
||||
return;
|
||||
}
|
||||
sm = new TetherInterfaceStateMachine(iface, mLooper, usb,
|
||||
sm = new TetherInterfaceStateMachine(iface, mLooper, interfaceType,
|
||||
mNMService, mStatsService, this);
|
||||
mIfaces.put(iface, sm);
|
||||
sm.start();
|
||||
@@ -412,24 +409,19 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
* for the specified interface.
|
||||
*/
|
||||
private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {
|
||||
boolean isProvisioningRequired = isTetherProvisioningRequired();
|
||||
boolean isProvisioningRequired = enable && isTetherProvisioningRequired();
|
||||
int result;
|
||||
switch (type) {
|
||||
case ConnectivityManager.TETHERING_WIFI:
|
||||
final WifiManager wifiManager =
|
||||
(WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
|
||||
if (wifiManager.setWifiApEnabled(null, enable)) {
|
||||
sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_NO_ERROR);
|
||||
if (enable && isProvisioningRequired) {
|
||||
scheduleProvisioningRechecks(type);
|
||||
}
|
||||
} else{
|
||||
sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
|
||||
result = setWifiTethering(enable);
|
||||
if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
|
||||
scheduleProvisioningRechecks(type);
|
||||
}
|
||||
sendTetherResult(receiver, result);
|
||||
break;
|
||||
case ConnectivityManager.TETHERING_USB:
|
||||
int result = setUsbTethering(enable);
|
||||
if (enable && isProvisioningRequired &&
|
||||
result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
|
||||
result = setUsbTethering(enable);
|
||||
if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
|
||||
scheduleProvisioningRechecks(type);
|
||||
}
|
||||
sendTetherResult(receiver, result);
|
||||
@@ -449,6 +441,20 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
}
|
||||
}
|
||||
|
||||
private int setWifiTethering(final boolean enable) {
|
||||
synchronized (mPublicSync) {
|
||||
// Note that we're maintaining a predicate that mWifiTetherRequested always matches
|
||||
// our last request to WifiManager re: its AP enabled status.
|
||||
mWifiTetherRequested = enable;
|
||||
final WifiManager wifiManager =
|
||||
(WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
|
||||
if (wifiManager.setWifiApEnabled(null /* use existing wifi config */, enable)) {
|
||||
return ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||
}
|
||||
return ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
|
||||
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (adapter == null || !adapter.isEnabled()) {
|
||||
@@ -770,7 +776,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
|
||||
// start tethering if we have a request pending
|
||||
if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
|
||||
tetherUsb(true);
|
||||
tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_USB);
|
||||
}
|
||||
mUsbTetherRequested = false;
|
||||
}
|
||||
@@ -782,31 +788,72 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
|
||||
mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
|
||||
}
|
||||
} else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
|
||||
synchronized (Tethering.this.mPublicSync) {
|
||||
if (!mWifiTetherRequested) {
|
||||
// We only care when we're trying to tether via our WiFi interface.
|
||||
return;
|
||||
}
|
||||
int curState = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
|
||||
WifiManager.WIFI_AP_STATE_DISABLED);
|
||||
switch (curState) {
|
||||
case WifiManager.WIFI_AP_STATE_ENABLING:
|
||||
// We can see this state on the way to both enabled and failure states.
|
||||
break;
|
||||
case WifiManager.WIFI_AP_STATE_ENABLED:
|
||||
// Tell an appropriate interface state machine that it should tether.
|
||||
tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_WIFI);
|
||||
break;
|
||||
case WifiManager.WIFI_AP_STATE_DISABLED:
|
||||
case WifiManager.WIFI_AP_STATE_DISABLING:
|
||||
case WifiManager.WIFI_AP_STATE_FAILED:
|
||||
default:
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" +
|
||||
curState);
|
||||
}
|
||||
// Tell an appropriate interface state machine that
|
||||
// it needs to tear itself down.
|
||||
tetherMatchingInterfaces(false, ConnectivityManager.TETHERING_WIFI);
|
||||
setWifiTethering(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
|
||||
updateConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void tetherUsb(boolean enable) {
|
||||
if (VDBG) Log.d(TAG, "tetherUsb " + enable);
|
||||
private void tetherMatchingInterfaces(boolean enable, int interfaceType) {
|
||||
if (VDBG) Log.d(TAG, "tetherMatchingInterfaces(" + enable + ", " + interfaceType + ")");
|
||||
|
||||
String[] ifaces = new String[0];
|
||||
String[] ifaces = null;
|
||||
try {
|
||||
ifaces = mNMService.listInterfaces();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error listing Interfaces", e);
|
||||
return;
|
||||
}
|
||||
for (String iface : ifaces) {
|
||||
if (isUsb(iface)) {
|
||||
int result = (enable ? tether(iface) : untether(iface));
|
||||
if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
|
||||
return;
|
||||
String chosenIface = null;
|
||||
if (ifaces != null) {
|
||||
for (String iface : ifaces) {
|
||||
if (ifaceNameToType(iface) == interfaceType) {
|
||||
chosenIface = iface;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.e(TAG, "unable start or stop USB tethering");
|
||||
if (chosenIface == null) {
|
||||
Log.e(TAG, "could not find iface of type " + interfaceType);
|
||||
return;
|
||||
}
|
||||
|
||||
int result = (enable ? tether(chosenIface) : untether(chosenIface));
|
||||
if (result != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
|
||||
Log.e(TAG, "unable start or stop tethering on iface " + chosenIface);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - return copies so people can't tamper
|
||||
@@ -831,7 +878,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
if (mRndisEnabled) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
tetherUsb(true);
|
||||
tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_USB);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -842,7 +889,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
} else {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
tetherUsb(false);
|
||||
tetherMatchingInterfaces(false, ConnectivityManager.TETHERING_USB);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -1410,15 +1457,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
for (String iface : ifaces) {
|
||||
TetherInterfaceStateMachine sm = mIfaces.get(iface);
|
||||
if (sm != null && sm.isTethered()) {
|
||||
if (isUsb(iface)) {
|
||||
tethered.add(new Integer(
|
||||
ConnectivityManager.TETHERING_USB));
|
||||
} else if (isWifi(iface)) {
|
||||
tethered.add(new Integer(
|
||||
ConnectivityManager.TETHERING_WIFI));
|
||||
} else if (isBluetooth(iface)) {
|
||||
tethered.add(new Integer(
|
||||
ConnectivityManager.TETHERING_BLUETOOTH));
|
||||
int interfaceType = ifaceNameToType(iface);
|
||||
if (interfaceType !=
|
||||
ConnectivityManager.TETHERING_INVALID) {
|
||||
tethered.add(new Integer(interfaceType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ import java.net.InetAddress;
|
||||
public class TetherInterfaceStateMachine extends StateMachine {
|
||||
private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
|
||||
private static final int USB_PREFIX_LENGTH = 24;
|
||||
private static final String WIFI_HOST_IFACE_ADDR = "192.168.43.1";
|
||||
private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24;
|
||||
|
||||
private final static String TAG = "TetherInterfaceSM";
|
||||
private final static boolean DBG = false;
|
||||
@@ -81,13 +83,13 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
private final INetworkStatsService mStatsService;
|
||||
private final IControlsTethering mTetherController;
|
||||
|
||||
private final boolean mUsb;
|
||||
private final String mIfaceName;
|
||||
private final int mInterfaceType;
|
||||
|
||||
private int mLastError;
|
||||
private String mMyUpstreamIfaceName; // may change over time
|
||||
|
||||
public TetherInterfaceStateMachine(String ifaceName, Looper looper, boolean usb,
|
||||
public TetherInterfaceStateMachine(String ifaceName, Looper looper, int interfaceType,
|
||||
INetworkManagementService nMService, INetworkStatsService statsService,
|
||||
IControlsTethering tetherController) {
|
||||
super(ifaceName, looper);
|
||||
@@ -95,7 +97,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
mStatsService = statsService;
|
||||
mTetherController = tetherController;
|
||||
mIfaceName = ifaceName;
|
||||
mUsb = usb;
|
||||
mInterfaceType = interfaceType;
|
||||
setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
|
||||
|
||||
mInitialState = new InitialState();
|
||||
@@ -143,25 +145,38 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
}
|
||||
|
||||
// configured when we start tethering and unconfig'd on error or conclusion
|
||||
private boolean configureUsbIface(boolean enabled, String iface) {
|
||||
if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
|
||||
private boolean configureIfaceIp(boolean enabled) {
|
||||
if (VDBG) Log.d(TAG, "configureIfaceIp(" + enabled + ")");
|
||||
|
||||
String ipAsString = null;
|
||||
int prefixLen = 0;
|
||||
if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
|
||||
ipAsString = USB_NEAR_IFACE_ADDR;
|
||||
prefixLen = USB_PREFIX_LENGTH;
|
||||
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
|
||||
ipAsString = WIFI_HOST_IFACE_ADDR;
|
||||
prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
|
||||
} else {
|
||||
// Nothing to do, BT does this elsewhere.
|
||||
return true;
|
||||
}
|
||||
|
||||
InterfaceConfiguration ifcg = null;
|
||||
try {
|
||||
ifcg = mNMService.getInterfaceConfig(iface);
|
||||
ifcg = mNMService.getInterfaceConfig(mIfaceName);
|
||||
if (ifcg != null) {
|
||||
InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
|
||||
ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
|
||||
InetAddress addr = NetworkUtils.numericToInetAddress(ipAsString);
|
||||
ifcg.setLinkAddress(new LinkAddress(addr, prefixLen));
|
||||
if (enabled) {
|
||||
ifcg.setInterfaceUp();
|
||||
} else {
|
||||
ifcg.setInterfaceDown();
|
||||
}
|
||||
ifcg.clearFlag("running");
|
||||
mNMService.setInterfaceConfig(iface, ifcg);
|
||||
mNMService.setInterfaceConfig(mIfaceName, ifcg);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error configuring interface " + iface, e);
|
||||
Log.e(TAG, "Error configuring interface " + mIfaceName, e);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -205,12 +220,10 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
class TetheredState extends State {
|
||||
@Override
|
||||
public void enter() {
|
||||
if (mUsb) {
|
||||
if (!configureUsbIface(true, mIfaceName)) {
|
||||
setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
|
||||
transitionTo(mInitialState);
|
||||
return;
|
||||
}
|
||||
if (!configureIfaceIp(true)) {
|
||||
setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
|
||||
transitionTo(mInitialState);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -242,9 +255,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
||||
Log.e(TAG, "Failed to untether interface: " + ee.toString());
|
||||
}
|
||||
|
||||
if (mUsb) {
|
||||
configureUsbIface(false, mIfaceName);
|
||||
}
|
||||
configureIfaceIp(false);
|
||||
}
|
||||
|
||||
private void cleanupUpstream() {
|
||||
|
||||
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.INetworkStatsService;
|
||||
import android.net.InterfaceConfiguration;
|
||||
import android.os.INetworkManagementService;
|
||||
@@ -56,8 +57,8 @@ public class TetherInterfaceStateMachineTest {
|
||||
private final TestLooper mLooper = new TestLooper();
|
||||
private TetherInterfaceStateMachine mTestedSm;
|
||||
|
||||
private void initStateMachine(boolean isUsb) throws Exception {
|
||||
mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(), isUsb,
|
||||
private void initStateMachine(int interfaceType) throws Exception {
|
||||
mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(), interfaceType,
|
||||
mNMService, mStatsService, mTetherHelper);
|
||||
mTestedSm.start();
|
||||
// Starting the state machine always puts us in a consistent state and notifies
|
||||
@@ -67,8 +68,8 @@ public class TetherInterfaceStateMachineTest {
|
||||
when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
|
||||
}
|
||||
|
||||
private void initTetheredStateMachine(boolean isUsb, String upstreamIface) throws Exception {
|
||||
initStateMachine(isUsb);
|
||||
private void initTetheredStateMachine(int interfaceType, String upstreamIface) throws Exception {
|
||||
initStateMachine(interfaceType);
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
|
||||
if (upstreamIface != null) {
|
||||
dispatchTetherConnectionChanged(upstreamIface);
|
||||
@@ -84,8 +85,8 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void startsOutAvailable() {
|
||||
mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(), false,
|
||||
mNMService, mStatsService, mTetherHelper);
|
||||
mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
|
||||
ConnectivityManager.TETHERING_BLUETOOTH, mNMService, mStatsService, mTetherHelper);
|
||||
mTestedSm.start();
|
||||
mLooper.dispatchAll();
|
||||
assertTrue("Should start out available for tethering", mTestedSm.isAvailable());
|
||||
@@ -97,7 +98,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void shouldDoNothingUntilRequested() throws Exception {
|
||||
initStateMachine(false);
|
||||
initStateMachine(ConnectivityManager.TETHERING_BLUETOOTH);
|
||||
final int [] NOOP_COMMANDS = {
|
||||
TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED,
|
||||
TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR,
|
||||
@@ -117,7 +118,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void handlesImmediateInterfaceDown() throws Exception {
|
||||
initStateMachine(false);
|
||||
initStateMachine(ConnectivityManager.TETHERING_BLUETOOTH);
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
|
||||
verify(mTetherHelper).sendTetherStateChangedBroadcast();
|
||||
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
|
||||
@@ -129,7 +130,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void canBeTethered() throws Exception {
|
||||
initStateMachine(false);
|
||||
initStateMachine(ConnectivityManager.TETHERING_BLUETOOTH);
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
|
||||
InOrder inOrder = inOrder(mTetherHelper, mNMService);
|
||||
inOrder.verify(mTetherHelper).notifyInterfaceTetheringReadiness(true, mTestedSm);
|
||||
@@ -144,7 +145,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void canUnrequestTethering() throws Exception {
|
||||
initTetheredStateMachine(false, null);
|
||||
initTetheredStateMachine(ConnectivityManager.TETHERING_BLUETOOTH, null);
|
||||
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
|
||||
InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
|
||||
@@ -159,7 +160,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void canBeTetheredAsUsb() throws Exception {
|
||||
initStateMachine(true);
|
||||
initStateMachine(ConnectivityManager.TETHERING_USB);
|
||||
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
|
||||
InOrder inOrder = inOrder(mTetherHelper, mNMService);
|
||||
@@ -177,7 +178,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void handlesFirstUpstreamChange() throws Exception {
|
||||
initTetheredStateMachine(false, null);
|
||||
initTetheredStateMachine(ConnectivityManager.TETHERING_BLUETOOTH, null);
|
||||
|
||||
// Telling the state machine about its upstream interface triggers a little more configuration.
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
|
||||
@@ -192,7 +193,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void handlesChangingUpstream() throws Exception {
|
||||
initTetheredStateMachine(false, UPSTREAM_IFACE);
|
||||
initTetheredStateMachine(ConnectivityManager.TETHERING_BLUETOOTH, UPSTREAM_IFACE);
|
||||
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
|
||||
InOrder inOrder = inOrder(mNMService, mStatsService);
|
||||
@@ -209,7 +210,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void canUnrequestTetheringWithUpstream() throws Exception {
|
||||
initTetheredStateMachine(false, UPSTREAM_IFACE);
|
||||
initTetheredStateMachine(ConnectivityManager.TETHERING_BLUETOOTH, UPSTREAM_IFACE);
|
||||
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
|
||||
InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
|
||||
@@ -228,7 +229,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
@Test
|
||||
public void interfaceDownLeadsToUnavailable() throws Exception {
|
||||
for (boolean shouldThrow : new boolean[]{true, false}) {
|
||||
initTetheredStateMachine(true, null);
|
||||
initTetheredStateMachine(ConnectivityManager.TETHERING_USB, null);
|
||||
|
||||
if (shouldThrow) {
|
||||
doThrow(RemoteException.class).when(mNMService).untetherInterface(IFACE_NAME);
|
||||
@@ -246,7 +247,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void usbShouldBeTornDownOnTetherError() throws Exception {
|
||||
initStateMachine(true);
|
||||
initStateMachine(ConnectivityManager.TETHERING_USB);
|
||||
|
||||
doThrow(RemoteException.class).when(mNMService).tetherInterface(IFACE_NAME);
|
||||
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
|
||||
@@ -263,7 +264,7 @@ public class TetherInterfaceStateMachineTest {
|
||||
|
||||
@Test
|
||||
public void shouldTearDownUsbOnUpstreamError() throws Exception {
|
||||
initTetheredStateMachine(true, null);
|
||||
initTetheredStateMachine(ConnectivityManager.TETHERING_USB, null);
|
||||
|
||||
doThrow(RemoteException.class).when(mNMService).enableNat(anyString(), anyString());
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
|
||||
|
||||
Reference in New Issue
Block a user