Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eaccec2d authored by Cody Kesting's avatar Cody Kesting Committed by Automerger Merge Worker
Browse files

Merge "Implement Safemode alarm in VcnGatewayConnection." am: 30d9bfa0 am:...

Merge "Implement Safemode alarm in VcnGatewayConnection." am: 30d9bfa0 am: 875a7d07 am: 8c576fb1 am: a843702c

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1577286

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I27c77ee59fe654397b6406dc7fb1aaa1023214c4
parents 554590be a843702c
Loading
Loading
Loading
Loading
+104 −4
Original line number Original line Diff line number Diff line
@@ -38,10 +38,12 @@ import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LinkProperties;
import android.net.Network;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkAgent;
import android.net.NetworkAgent.ValidationStatus;
import android.net.NetworkAgentConfig;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkCapabilities;
import android.net.RouteInfo;
import android.net.RouteInfo;
import android.net.TelephonyNetworkSpecifier;
import android.net.TelephonyNetworkSpecifier;
import android.net.Uri;
import android.net.annotations.PolicyDirection;
import android.net.annotations.PolicyDirection;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionConfiguration;
import android.net.ipsec.ike.ChildSessionConfiguration;
@@ -151,6 +153,9 @@ public class VcnGatewayConnection extends StateMachine {
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static final String RETRY_TIMEOUT_ALARM = TAG + "_RETRY_TIMEOUT_ALARM";
    static final String RETRY_TIMEOUT_ALARM = TAG + "_RETRY_TIMEOUT_ALARM";


    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static final String SAFEMODE_TIMEOUT_ALARM = TAG + "_SAFEMODE_TIMEOUT_ALARM";

    private static final int[] MERGED_CAPABILITIES =
    private static final int[] MERGED_CAPABILITIES =
            new int[] {NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_NOT_ROAMING};
            new int[] {NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_NOT_ROAMING};
    private static final int ARG_NOT_PRESENT = Integer.MIN_VALUE;
    private static final int ARG_NOT_PRESENT = Integer.MIN_VALUE;
@@ -167,6 +172,9 @@ public class VcnGatewayConnection extends StateMachine {
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static final int TEARDOWN_TIMEOUT_SECONDS = 5;
    static final int TEARDOWN_TIMEOUT_SECONDS = 5;


    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static final int SAFEMODE_TIMEOUT_SECONDS = 30;

    private interface EventInfo {}
    private interface EventInfo {}


    /**
    /**
@@ -409,6 +417,23 @@ public class VcnGatewayConnection extends StateMachine {
    // TODO(b/178426520): implement handling of this event
    // TODO(b/178426520): implement handling of this event
    private static final int EVENT_SUBSCRIPTIONS_CHANGED = 9;
    private static final int EVENT_SUBSCRIPTIONS_CHANGED = 9;


    /**
     * Sent when this VcnGatewayConnection has entered Safemode.
     *
     * <p>A VcnGatewayConnection enters Safemode when it takes over {@link
     * #SAFEMODE_TIMEOUT_SECONDS} to enter {@link ConnectedState}.
     *
     * <p>When a VcnGatewayConnection enters safe mode, it will fire {@link
     * VcnGatewayStatusCallback#onEnteredSafemode()} to notify its Vcn. The Vcn will then shut down
     * its VcnGatewayConnectin(s).
     *
     * <p>Relevant in DisconnectingState, ConnectingState, ConnectedState (if the Vcn Network is not
     * validated yet), and RetryTimeoutState.
     *
     * @param arg1 The "all" token; this signal is always honored.
     */
    private static final int EVENT_SAFEMODE_TIMEOUT_EXCEEDED = 10;

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    @NonNull
    @NonNull
    final DisconnectedState mDisconnectedState = new DisconnectedState();
    final DisconnectedState mDisconnectedState = new DisconnectedState();
@@ -520,11 +545,13 @@ public class VcnGatewayConnection extends StateMachine {
     * <p>Set in Connected state, always @NonNull in Connected, Migrating states, @Nullable
     * <p>Set in Connected state, always @NonNull in Connected, Migrating states, @Nullable
     * otherwise.
     * otherwise.
     */
     */
    private NetworkAgent mNetworkAgent;
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    NetworkAgent mNetworkAgent;


    @Nullable private WakeupMessage mTeardownTimeoutAlarm;
    @Nullable private WakeupMessage mTeardownTimeoutAlarm;
    @Nullable private WakeupMessage mDisconnectRequestAlarm;
    @Nullable private WakeupMessage mDisconnectRequestAlarm;
    @Nullable private WakeupMessage mRetryTimeoutAlarm;
    @Nullable private WakeupMessage mRetryTimeoutAlarm;
    @Nullable private WakeupMessage mSafemodeTimeoutAlarm;


    public VcnGatewayConnection(
    public VcnGatewayConnection(
            @NonNull VcnContext vcnContext,
            @NonNull VcnContext vcnContext,
@@ -611,6 +638,7 @@ public class VcnGatewayConnection extends StateMachine {
        cancelTeardownTimeoutAlarm();
        cancelTeardownTimeoutAlarm();
        cancelDisconnectRequestAlarm();
        cancelDisconnectRequestAlarm();
        cancelRetryTimeoutAlarm();
        cancelRetryTimeoutAlarm();
        cancelSafemodeAlarm();


        mUnderlyingNetworkTracker.teardown();
        mUnderlyingNetworkTracker.teardown();
    }
    }
@@ -899,6 +927,30 @@ public class VcnGatewayConnection extends StateMachine {
        removeEqualMessages(EVENT_RETRY_TIMEOUT_EXPIRED);
        removeEqualMessages(EVENT_RETRY_TIMEOUT_EXPIRED);
    }
    }


    @VisibleForTesting(visibility = Visibility.PRIVATE)
    void setSafemodeAlarm() {
        // Only schedule a NEW alarm if none is already set.
        if (mSafemodeTimeoutAlarm != null) {
            return;
        }

        final Message delayedMessage = obtainMessage(EVENT_SAFEMODE_TIMEOUT_EXCEEDED, TOKEN_ALL);
        mSafemodeTimeoutAlarm =
                createScheduledAlarm(
                        SAFEMODE_TIMEOUT_ALARM,
                        delayedMessage,
                        TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
    }

    private void cancelSafemodeAlarm() {
        if (mSafemodeTimeoutAlarm != null) {
            mSafemodeTimeoutAlarm.cancel();
            mSafemodeTimeoutAlarm = null;
        }

        removeEqualMessages(EVENT_SAFEMODE_TIMEOUT_EXCEEDED);
    }

    private void sessionLost(int token, @Nullable Exception exception) {
    private void sessionLost(int token, @Nullable Exception exception) {
        sendMessageAndAcquireWakeLock(
        sendMessageAndAcquireWakeLock(
                EVENT_SESSION_LOST, token, new EventSessionLostInfo(exception));
                EVENT_SESSION_LOST, token, new EventSessionLostInfo(exception));
@@ -1072,6 +1124,8 @@ public class VcnGatewayConnection extends StateMachine {
            if (mIkeSession != null || mNetworkAgent != null) {
            if (mIkeSession != null || mNetworkAgent != null) {
                Slog.wtf(TAG, "Active IKE Session or NetworkAgent in DisconnectedState");
                Slog.wtf(TAG, "Active IKE Session or NetworkAgent in DisconnectedState");
            }
            }

            cancelSafemodeAlarm();
        }
        }


        @Override
        @Override
@@ -1095,6 +1149,12 @@ public class VcnGatewayConnection extends StateMachine {
                    break;
                    break;
            }
            }
        }
        }

        @Override
        protected void exitState() {
            // Safe to blindly set up, as it is cancelled and cleared on entering this state
            setSafemodeAlarm();
        }
    }
    }


    private abstract class ActiveBaseState extends BaseState {
    private abstract class ActiveBaseState extends BaseState {
@@ -1185,6 +1245,10 @@ public class VcnGatewayConnection extends StateMachine {
                        transitionTo(mDisconnectedState);
                        transitionTo(mDisconnectedState);
                    }
                    }
                    break;
                    break;
                case EVENT_SAFEMODE_TIMEOUT_EXCEEDED:
                    mGatewayStatusCallback.onEnteredSafemode();
                    mSafemodeTimeoutAlarm = null;
                    break;
                default:
                default:
                    logUnhandledMessage(msg);
                    logUnhandledMessage(msg);
                    break;
                    break;
@@ -1267,6 +1331,10 @@ public class VcnGatewayConnection extends StateMachine {
                case EVENT_DISCONNECT_REQUESTED:
                case EVENT_DISCONNECT_REQUESTED:
                    handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason);
                    handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason);
                    break;
                    break;
                case EVENT_SAFEMODE_TIMEOUT_EXCEEDED:
                    mGatewayStatusCallback.onEnteredSafemode();
                    mSafemodeTimeoutAlarm = null;
                    break;
                default:
                default:
                    logUnhandledMessage(msg);
                    logUnhandledMessage(msg);
                    break;
                    break;
@@ -1310,6 +1378,14 @@ public class VcnGatewayConnection extends StateMachine {
                        public void unwanted() {
                        public void unwanted() {
                            teardownAsynchronously();
                            teardownAsynchronously();
                        }
                        }

                        @Override
                        public void onValidationStatus(
                                @ValidationStatus int status, @Nullable Uri redirectUri) {
                            if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
                                clearFailedAttemptCounterAndSafeModeAlarm();
                            }
                        }
                    };
                    };


            agent.register();
            agent.register();
@@ -1318,6 +1394,14 @@ public class VcnGatewayConnection extends StateMachine {
            return agent;
            return agent;
        }
        }


        protected void clearFailedAttemptCounterAndSafeModeAlarm() {
            mVcnContext.ensureRunningOnLooperThread();

            // Validated connection, clear failed attempt counter
            mFailedAttempts = 0;
            cancelSafemodeAlarm();
        }

        protected void applyTransform(
        protected void applyTransform(
                int token,
                int token,
                @NonNull IpSecTunnelInterface tunnelIface,
                @NonNull IpSecTunnelInterface tunnelIface,
@@ -1397,9 +1481,6 @@ public class VcnGatewayConnection extends StateMachine {
                    teardownAsynchronously();
                    teardownAsynchronously();
                }
                }
            }
            }

            // Successful connection, clear failed attempt counter
            mFailedAttempts = 0;
        }
        }


        @Override
        @Override
@@ -1436,6 +1517,10 @@ public class VcnGatewayConnection extends StateMachine {
                case EVENT_DISCONNECT_REQUESTED:
                case EVENT_DISCONNECT_REQUESTED:
                    handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason);
                    handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason);
                    break;
                    break;
                case EVENT_SAFEMODE_TIMEOUT_EXCEEDED:
                    mGatewayStatusCallback.onEnteredSafemode();
                    mSafemodeTimeoutAlarm = null;
                    break;
                default:
                default:
                    logUnhandledMessage(msg);
                    logUnhandledMessage(msg);
                    break;
                    break;
@@ -1478,7 +1563,18 @@ public class VcnGatewayConnection extends StateMachine {
                mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig);
                mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig);
            } else {
            } else {
                updateNetworkAgent(tunnelIface, mNetworkAgent, childConfig);
                updateNetworkAgent(tunnelIface, mNetworkAgent, childConfig);

                // mNetworkAgent not null, so the VCN Network has already been established. Clear
                // the failed attempt counter and safe mode alarm since this transition is complete.
                clearFailedAttemptCounterAndSafeModeAlarm();
            }
        }
        }

        @Override
        protected void exitState() {
            // Attempt to set the safe mode alarm - this requires the Vcn Network being validated
            // while in ConnectedState (which cancels the previous alarm)
            setSafemodeAlarm();
        }
        }
    }
    }


@@ -1526,6 +1622,10 @@ public class VcnGatewayConnection extends StateMachine {
                case EVENT_DISCONNECT_REQUESTED:
                case EVENT_DISCONNECT_REQUESTED:
                    handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason);
                    handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason);
                    break;
                    break;
                case EVENT_SAFEMODE_TIMEOUT_EXCEEDED:
                    mGatewayStatusCallback.onEnteredSafemode();
                    mSafemodeTimeoutAlarm = null;
                    break;
                default:
                default:
                    logUnhandledMessage(msg);
                    logUnhandledMessage(msg);
                    break;
                    break;
+28 −1
Original line number Original line Diff line number Diff line
@@ -34,8 +34,10 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;


import android.net.LinkProperties;
import android.net.LinkProperties;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkCapabilities;


import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
@@ -72,6 +74,11 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
        verify(mDeps).newIkeSession(any(), any(), any(), any(), any());
        verify(mDeps).newIkeSession(any(), any(), any(), any(), any());
    }
    }


    @Test
    public void testEnterStateDoesNotCancelSafemodeAlarm() {
        verifySafemodeTimeoutAlarmAndGetCallback(false /* expectCanceled */);
    }

    @Test
    @Test
    public void testNullNetworkDoesNotTriggerDisconnect() throws Exception {
    public void testNullNetworkDoesNotTriggerDisconnect() throws Exception {
        mGatewayConnection
        mGatewayConnection
@@ -122,6 +129,9 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection


    @Test
    @Test
    public void testChildOpenedRegistersNetwork() throws Exception {
    public void testChildOpenedRegistersNetwork() throws Exception {
        // Verify scheduled but not canceled when entering ConnectedState
        verifySafemodeTimeoutAlarmAndGetCallback(false /* expectCanceled */);

        final VcnChildSessionConfiguration mMockChildSessionConfig =
        final VcnChildSessionConfiguration mMockChildSessionConfig =
                mock(VcnChildSessionConfiguration.class);
                mock(VcnChildSessionConfiguration.class);
        doReturn(Collections.singletonList(TEST_INTERNAL_ADDR))
        doReturn(Collections.singletonList(TEST_INTERNAL_ADDR))
@@ -163,24 +173,41 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
        for (int cap : mConfig.getAllExposedCapabilities()) {
        for (int cap : mConfig.getAllExposedCapabilities()) {
            assertTrue(nc.hasCapability(cap));
            assertTrue(nc.hasCapability(cap));
        }
        }

        // Now that Vcn Network is up, notify it as validated and verify the Safemode alarm is
        // canceled
        mGatewayConnection.mNetworkAgent.onValidationStatus(
                NetworkAgent.VALIDATION_STATUS_VALID, null /* redirectUri */);
        verify(mSafemodeTimeoutAlarm).cancel();
    }
    }


    @Test
    @Test
    public void testChildSessionClosedTriggersDisconnect() throws Exception {
    public void testChildSessionClosedTriggersDisconnect() throws Exception {
        // Verify scheduled but not canceled when entering ConnectedState
        verifySafemodeTimeoutAlarmAndGetCallback(false /* expectCanceled */);

        getChildSessionCallback().onClosed();
        getChildSessionCallback().onClosed();
        mTestLooper.dispatchAll();
        mTestLooper.dispatchAll();


        assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
        assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
        verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */);
        verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */);

        // Since network never validated, verify mSafemodeTimeoutAlarm not canceled
        verifyNoMoreInteractions(mSafemodeTimeoutAlarm);
    }
    }


    @Test
    @Test
    public void testIkeSessionClosedTriggersDisconnect() throws Exception {
    public void testIkeSessionClosedTriggersDisconnect() throws Exception {
        // Verify scheduled but not canceled when entering ConnectedState
        verifySafemodeTimeoutAlarmAndGetCallback(false /* expectCanceled */);

        getIkeSessionCallback().onClosed();
        getIkeSessionCallback().onClosed();
        mTestLooper.dispatchAll();
        mTestLooper.dispatchAll();


        assertEquals(mGatewayConnection.mRetryTimeoutState, mGatewayConnection.getCurrentState());
        assertEquals(mGatewayConnection.mRetryTimeoutState, mGatewayConnection.getCurrentState());
        verify(mIkeSession).close();
        verify(mIkeSession).close();
        verifyTeardownTimeoutAlarmAndGetCallback(true /* expectCanceled */);

        // Since network never validated, verify mSafemodeTimeoutAlarm not canceled
        verifyNoMoreInteractions(mSafemodeTimeoutAlarm);
    }
    }
}
}
+5 −0
Original line number Original line Diff line number Diff line
@@ -106,4 +106,9 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio
        verify(mIkeSession).close();
        verify(mIkeSession).close();
        verifyTeardownTimeoutAlarmAndGetCallback(true /* expectCanceled */);
        verifyTeardownTimeoutAlarmAndGetCallback(true /* expectCanceled */);
    }
    }

    @Test
    public void testSafemodeTimeoutNotifiesCallback() {
        verifySafemodeTimeoutNotifiesCallback(mGatewayConnection.mConnectingState);
    }
}
}
+4 −1
Original line number Original line Diff line number Diff line
@@ -48,7 +48,8 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect
                        .createIpSecTunnelInterface(
                        .createIpSecTunnelInterface(
                                DUMMY_ADDR, DUMMY_ADDR, TEST_UNDERLYING_NETWORK_RECORD_1.network);
                                DUMMY_ADDR, DUMMY_ADDR, TEST_UNDERLYING_NETWORK_RECORD_1.network);
        mGatewayConnection.setTunnelInterface(tunnelIface);
        mGatewayConnection.setTunnelInterface(tunnelIface);
        mGatewayConnection.transitionTo(mGatewayConnection.mDisconnectedState);

        // Don't need to transition to DisconnectedState because it is the starting state
        mTestLooper.dispatchAll();
        mTestLooper.dispatchAll();
    }
    }


@@ -78,6 +79,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect
        mTestLooper.dispatchAll();
        mTestLooper.dispatchAll();


        assertEquals(mGatewayConnection.mConnectingState, mGatewayConnection.getCurrentState());
        assertEquals(mGatewayConnection.mConnectingState, mGatewayConnection.getCurrentState());
        verifySafemodeTimeoutAlarmAndGetCallback(false /* expectCanceled */);
    }
    }


    @Test
    @Test
@@ -98,5 +100,6 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect


        assertNull(mGatewayConnection.getCurrentState());
        assertNull(mGatewayConnection.getCurrentState());
        verify(mIpSecSvc).deleteTunnelInterface(eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), any());
        verify(mIpSecSvc).deleteTunnelInterface(eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), any());
        verifySafemodeTimeoutAlarmAndGetCallback(true /* expectCanceled */);
    }
    }
}
}
+5 −0
Original line number Original line Diff line number Diff line
@@ -80,4 +80,9 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec
        assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
        assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
        verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */);
        verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */);
    }
    }

    @Test
    public void testSafemodeTimeoutNotifiesCallback() {
        verifySafemodeTimeoutNotifiesCallback(mGatewayConnection.mDisconnectingState);
    }
}
}
Loading