Merge "Add base states with exception catching and utility functions"
This commit is contained in:
@@ -123,7 +123,7 @@ public class VcnGatewayConnection extends StateMachine {
|
||||
private static final String DISCONNECT_REASON_UNDERLYING_NETWORK_LOST =
|
||||
"Underlying Network lost";
|
||||
private static final String DISCONNECT_REASON_TEARDOWN = "teardown() called on VcnTunnel";
|
||||
private static final int TOKEN_ANY = Integer.MIN_VALUE;
|
||||
private static final int TOKEN_ALL = Integer.MIN_VALUE;
|
||||
|
||||
private static final int NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS = 30;
|
||||
private static final int TEARDOWN_TIMEOUT_SECONDS = 5;
|
||||
@@ -139,7 +139,7 @@ public class VcnGatewayConnection extends StateMachine {
|
||||
*
|
||||
* <p>In the Connected state, this MAY indicate a mobility even occurred.
|
||||
*
|
||||
* @param arg1 The "any" token; this event is always applicable.
|
||||
* @param arg1 The "all" token; this event is always applicable.
|
||||
* @param obj @NonNull An EventUnderlyingNetworkChangedInfo instance with relevant data.
|
||||
*/
|
||||
private static final int EVENT_UNDERLYING_NETWORK_CHANGED = 1;
|
||||
@@ -175,7 +175,7 @@ public class VcnGatewayConnection extends StateMachine {
|
||||
* <p>Upon receipt of this signal, the state machine will transition from the Retry-timeout
|
||||
* state to the Connecting state.
|
||||
*
|
||||
* @param arg1 The "any" token; no sessions are active in the RetryTimeoutState.
|
||||
* @param arg1 The "all" token; no sessions are active in the RetryTimeoutState.
|
||||
*/
|
||||
private static final int EVENT_RETRY_TIMEOUT_EXPIRED = 2;
|
||||
|
||||
@@ -318,7 +318,7 @@ public class VcnGatewayConnection extends StateMachine {
|
||||
* <p>Upon receipt of this signal, the state machine MUST tear down all active sessions, cancel
|
||||
* any pending work items, and move to the Disconnected state.
|
||||
*
|
||||
* @param arg1 The "any" token; this signal is always honored.
|
||||
* @param arg1 The "all" token; this signal is always honored.
|
||||
* @param obj @NonNull An EventDisconnectRequestedInfo instance with relevant data.
|
||||
*/
|
||||
private static final int EVENT_DISCONNECT_REQUESTED = 7;
|
||||
@@ -504,16 +504,9 @@ public class VcnGatewayConnection extends StateMachine {
|
||||
* <p>Once torn down, this VcnTunnel CANNOT be started again.
|
||||
*/
|
||||
public void teardownAsynchronously() {
|
||||
mUnderlyingNetworkTracker.teardown();
|
||||
|
||||
// No need to call setInterfaceDown(); the IpSecInterface is being fully torn down.
|
||||
if (mTunnelIface != null) {
|
||||
mTunnelIface.close();
|
||||
}
|
||||
|
||||
sendMessage(
|
||||
EVENT_DISCONNECT_REQUESTED,
|
||||
TOKEN_ANY,
|
||||
TOKEN_ALL,
|
||||
new EventDisconnectRequestedInfo(DISCONNECT_REASON_TEARDOWN));
|
||||
quit();
|
||||
|
||||
@@ -521,6 +514,16 @@ public class VcnGatewayConnection extends StateMachine {
|
||||
// is also called asynchronously when a NetworkAgent becomes unwanted
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onQuitting() {
|
||||
// No need to call setInterfaceDown(); the IpSecInterface is being fully torn down.
|
||||
if (mTunnelIface != null) {
|
||||
mTunnelIface.close();
|
||||
}
|
||||
|
||||
mUnderlyingNetworkTracker.teardown();
|
||||
}
|
||||
|
||||
private class VcnUnderlyingNetworkTrackerCallback implements UnderlyingNetworkTrackerCallback {
|
||||
@Override
|
||||
public void onSelectedUnderlyingNetworkChanged(
|
||||
@@ -530,26 +533,24 @@ public class VcnGatewayConnection extends StateMachine {
|
||||
if (underlying == null) {
|
||||
sendMessageDelayed(
|
||||
EVENT_DISCONNECT_REQUESTED,
|
||||
TOKEN_ANY,
|
||||
TOKEN_ALL,
|
||||
new EventDisconnectRequestedInfo(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST),
|
||||
TimeUnit.SECONDS.toMillis(NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS));
|
||||
return;
|
||||
}
|
||||
} else if (getHandler() != null) {
|
||||
// Cancel any existing disconnect due to loss of underlying network
|
||||
// getHandler() can return null if the state machine has already quit. Since this is
|
||||
// called from other classes, this condition must be verified.
|
||||
|
||||
// Cancel any existing disconnect due to loss of underlying network
|
||||
// getHandler() can return null if the state machine has already quit. Since this is
|
||||
// called
|
||||
// from other classes, this condition must be verified.
|
||||
if (getHandler() != null) {
|
||||
getHandler()
|
||||
.removeEqualMessages(
|
||||
EVENT_DISCONNECT_REQUESTED,
|
||||
new EventDisconnectRequestedInfo(
|
||||
DISCONNECT_REASON_UNDERLYING_NETWORK_LOST));
|
||||
}
|
||||
|
||||
sendMessage(
|
||||
EVENT_UNDERLYING_NETWORK_CHANGED,
|
||||
TOKEN_ANY,
|
||||
TOKEN_ALL,
|
||||
new EventUnderlyingNetworkChangedInfo(underlying));
|
||||
}
|
||||
}
|
||||
@@ -594,10 +595,101 @@ public class VcnGatewayConnection extends StateMachine {
|
||||
}
|
||||
|
||||
private abstract class BaseState extends State {
|
||||
@Override
|
||||
public void enter() {
|
||||
try {
|
||||
enterState();
|
||||
} catch (Exception e) {
|
||||
Slog.wtf(TAG, "Uncaught exception", e);
|
||||
sendMessage(
|
||||
EVENT_DISCONNECT_REQUESTED,
|
||||
TOKEN_ALL,
|
||||
new EventDisconnectRequestedInfo(
|
||||
DISCONNECT_REASON_INTERNAL_ERROR + e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
protected void enterState() throws Exception {}
|
||||
|
||||
/**
|
||||
* Top-level processMessage with safeguards to prevent crashing the System Server on non-eng
|
||||
* builds.
|
||||
*/
|
||||
@Override
|
||||
public boolean processMessage(Message msg) {
|
||||
try {
|
||||
processStateMsg(msg);
|
||||
} catch (Exception e) {
|
||||
Slog.wtf(TAG, "Uncaught exception", e);
|
||||
sendMessage(
|
||||
EVENT_DISCONNECT_REQUESTED,
|
||||
TOKEN_ALL,
|
||||
new EventDisconnectRequestedInfo(
|
||||
DISCONNECT_REASON_INTERNAL_ERROR + e.toString()));
|
||||
}
|
||||
|
||||
return HANDLED;
|
||||
}
|
||||
|
||||
protected abstract void processStateMsg(Message msg) throws Exception;
|
||||
|
||||
protected void logUnhandledMessage(Message msg) {
|
||||
// Log as unexpected all known messages, and log all else as unknown.
|
||||
switch (msg.what) {
|
||||
case EVENT_UNDERLYING_NETWORK_CHANGED: // Fallthrough
|
||||
case EVENT_RETRY_TIMEOUT_EXPIRED: // Fallthrough
|
||||
case EVENT_SESSION_LOST: // Fallthrough
|
||||
case EVENT_SESSION_CLOSED: // Fallthrough
|
||||
case EVENT_TRANSFORM_CREATED: // Fallthrough
|
||||
case EVENT_SETUP_COMPLETED: // Fallthrough
|
||||
case EVENT_DISCONNECT_REQUESTED: // Fallthrough
|
||||
case EVENT_TEARDOWN_TIMEOUT_EXPIRED:
|
||||
logUnexpectedEvent(msg.what);
|
||||
break;
|
||||
default:
|
||||
logWtfUnknownEvent(msg.what);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected void teardownNetwork() {
|
||||
if (mNetworkAgent != null) {
|
||||
mNetworkAgent.sendNetworkInfo(buildNetworkInfo(false /* isConnected */));
|
||||
mNetworkAgent = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void teardownIke() {
|
||||
if (mIkeSession != null) {
|
||||
mIkeSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleDisconnectRequested(String msg) {
|
||||
Slog.v(TAG, "Tearing down. Cause: " + msg);
|
||||
teardownNetwork();
|
||||
teardownIke();
|
||||
|
||||
if (mIkeSession == null) {
|
||||
// Already disconnected, go straight to DisconnectedState
|
||||
transitionTo(mDisconnectedState);
|
||||
} else {
|
||||
// Still need to wait for full closure
|
||||
transitionTo(mDisconnectingState);
|
||||
}
|
||||
}
|
||||
|
||||
protected void logUnexpectedEvent(int what) {
|
||||
Slog.d(TAG, String.format(
|
||||
"Unexpected event code %d in state %s", what, this.getClass().getSimpleName()));
|
||||
}
|
||||
|
||||
protected void logWtfUnknownEvent(int what) {
|
||||
Slog.wtf(TAG, String.format(
|
||||
"Unknown event code %d in state %s", what, this.getClass().getSimpleName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* State representing the a disconnected VCN tunnel.
|
||||
*
|
||||
@@ -608,7 +700,29 @@ public class VcnGatewayConnection extends StateMachine {
|
||||
protected void processStateMsg(Message msg) {}
|
||||
}
|
||||
|
||||
private abstract class ActiveBaseState extends BaseState {}
|
||||
private abstract class ActiveBaseState extends BaseState {
|
||||
/**
|
||||
* Handles all incoming messages, discarding messages for previous networks.
|
||||
*
|
||||
* <p>States that handle mobility events may need to override this method to receive
|
||||
* messages for all underlying networks.
|
||||
*/
|
||||
@Override
|
||||
public boolean processMessage(Message msg) {
|
||||
final int token = msg.arg1;
|
||||
// Only process if a valid token is presented.
|
||||
if (isValidToken(token)) {
|
||||
return super.processMessage(msg);
|
||||
}
|
||||
|
||||
Slog.v(TAG, "Message called with obsolete token: " + token + "; what: " + msg.what);
|
||||
return HANDLED;
|
||||
}
|
||||
|
||||
protected boolean isValidToken(int token) {
|
||||
return (token == TOKEN_ALL || token == mCurrentToken);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transitive state representing a VCN that is tearing down an IKE session.
|
||||
|
||||
Reference in New Issue
Block a user