Loading services/core/java/com/android/server/vcn/VcnGatewayConnection.java +136 −22 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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( Loading @@ -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. if (getHandler() != null) { // called from other classes, this condition must be verified. getHandler() .removeEqualMessages( EVENT_DISCONNECT_REQUESTED, new EventDisconnectRequestedInfo( DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)); } sendMessage( EVENT_UNDERLYING_NETWORK_CHANGED, TOKEN_ANY, TOKEN_ALL, new EventUnderlyingNetworkChangedInfo(underlying)); } } Loading Loading @@ -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. * Loading @@ -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. Loading Loading
services/core/java/com/android/server/vcn/VcnGatewayConnection.java +136 −22 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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( Loading @@ -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. if (getHandler() != null) { // called from other classes, this condition must be verified. getHandler() .removeEqualMessages( EVENT_DISCONNECT_REQUESTED, new EventDisconnectRequestedInfo( DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)); } sendMessage( EVENT_UNDERLYING_NETWORK_CHANGED, TOKEN_ANY, TOKEN_ALL, new EventUnderlyingNetworkChangedInfo(underlying)); } } Loading Loading @@ -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. * Loading @@ -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. Loading