Merge "Add base states with exception catching and utility functions"

This commit is contained in:
Benedict Wong
2021-01-21 20:12:52 +00:00
committed by Gerrit Code Review

View File

@@ -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.