Fix dead lock in Tethering state machine

This fix is for tethering from N MR1. It reserves the same idea
originally in e4bdfd8ad86a013c5a2ee8964119393cea1ec4a3.

Tethering is animated by two state machines. If an error occurs,
one of the state machine notifies the other and definitely stays
in the error state while the other retries the tether operation
after having treated the error.

An example is when dnsmasq is started by calling tether(), but while it
hasn't finished starting yet untether() is called asynchronously
by a different tethering. Then "Setting DNS forwarders failed!" error
occurs and device can't be tethered anymore without reboot.

This patch allows to clear the error of the blocked state machine
from the other one and thus recover a normal cycle.

Test: fastly switching USB/Wi-Fi tethering On/Off repeatedly
Test: manually kill dnsmasq during BT tethering then turn on
      Wi-Fi tethering

Change-Id: Ide062dd4c15a0e7c72eced9a5fe807f845d4ea9c
This commit is contained in:
Yohei, Oshima
2016-12-08 13:39:20 +09:00
committed by Nguyen Vu Thanh Tung
parent 05550d9ed8
commit 977aad5a65
2 changed files with 14 additions and 1 deletions

View File

@@ -950,6 +950,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
// Events from NetworkCallbacks that we process on the master state
// machine thread on behalf of the UpstreamNetworkMonitor.
static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5;
// we treated the error and want now to clear it
static final int CMD_CLEAR_ERROR = BASE_MASTER + 6;
private State mInitialState;
private State mTetherModeAliveState;
@@ -1487,6 +1489,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
who.sendMessage(mErrorNotification);
break;
case CMD_CLEAR_ERROR:
mErrorNotification = ConnectivityManager.TETHER_ERROR_NO_ERROR;
transitionTo(mInitialState);
break;
default:
retValue = false;
}
@@ -1631,6 +1637,12 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
// Not really very much we can do here.
}
// If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
// Thus we give a chance for TetherMasterSM to recover to InitialState
// by sending CMD_CLEAR_ERROR
if (error == ConnectivityManager.TETHER_ERROR_MASTER_ERROR) {
mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who);
}
switch (state) {
case IControlsTethering.STATE_UNAVAILABLE:
case IControlsTethering.STATE_AVAILABLE:

View File

@@ -167,7 +167,8 @@ public class TetherInterfaceStateMachine extends StateMachine {
private void maybeLogMessage(State state, int what) {
if (DBG) {
Log.d(TAG, state.getName() + " got " +
sMagicDecoderRing.get(what, Integer.toString(what)));
sMagicDecoderRing.get(what, Integer.toString(what)) + ", Iface = " +
mIfaceName);
}
}