summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/vcn/VcnGatewayConnection.java158
1 files changed, 136 insertions, 22 deletions
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 7024e67a8204..4e0c0c54923b 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -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.