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

Commit 924207c4 authored by Lucas Lin's avatar Lucas Lin Committed by Android (Google) Code Review
Browse files

Merge changes from topic "cherrypicker-L42100000956041116:N02800001288713842" into tm-qpr-dev

* changes:
  Tidy up VPN code
  Improve the code of handleSessionLost()
parents 1204dd86 bf56a800
Loading
Loading
Loading
Loading
+74 −116
Original line number Diff line number Diff line
@@ -222,6 +222,11 @@ public class Vpn {
     */
    private static final int VPN_DEFAULT_SCORE = 101;

    /**
     * The initial token value of IKE session.
     */
    private static final int STARTING_TOKEN = -1;

    // TODO: create separate trackers for each unique VPN to support
    // automated reconnection

@@ -795,7 +800,7 @@ public class Vpn {
        }
    }

    private boolean isVpnApp(String packageName) {
    private static boolean isVpnApp(String packageName) {
        return packageName != null && !VpnConfig.LEGACY_VPN.equals(packageName);
    }

@@ -2593,7 +2598,7 @@ public class Vpn {
    }

    @Nullable
    protected synchronized NetworkCapabilities getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
    private synchronized NetworkCapabilities getRedactedNetworkCapabilities(
            NetworkCapabilities nc) {
        if (nc == null) return null;
        return mConnectivityManager.getRedactedNetworkCapabilitiesForPackage(
@@ -2601,8 +2606,7 @@ public class Vpn {
    }

    @Nullable
    protected synchronized LinkProperties getRedactedLinkPropertiesOfUnderlyingNetwork(
            LinkProperties lp) {
    private synchronized LinkProperties getRedactedLinkProperties(LinkProperties lp) {
        if (lp == null) return null;
        return mConnectivityManager.getRedactedLinkPropertiesForPackage(lp, mOwnerUID, mPackage);
    }
@@ -2716,11 +2720,13 @@ public class Vpn {
        private boolean mIsRunning = true;

        /**
         * The token used by the primary/current/active IKE session.
         * The token that identifies the most recently created IKE session.
         *
         * <p>This token MUST be updated when the VPN switches to use a new IKE session.
         * <p>This token is monotonically increasing and will never be reset in the lifetime of this
         * Ikev2VpnRunner, but it does get reset across runs. It also MUST be accessed on the
         * executor thread and updated when a new IKE session is created.
         */
        private int mCurrentToken = -1;
        private int mCurrentToken = STARTING_TOKEN;

        @Nullable private IpSecTunnelInterface mTunnelIface;
        @Nullable private Network mActiveNetwork;
@@ -3223,7 +3229,7 @@ public class Vpn {
                        mExecutor.schedule(
                                () -> {
                                    if (isActiveToken(token)) {
                                        handleSessionLost(null, network);
                                        handleSessionLost(null /* exception */, network);
                                    } else {
                                        Log.d(
                                                TAG,
@@ -3240,7 +3246,7 @@ public class Vpn {
                                TimeUnit.MILLISECONDS);
            } else {
                Log.d(TAG, "Call handleSessionLost for losing network " + network);
                handleSessionLost(null, network);
                handleSessionLost(null /* exception */, network);
            }
        }

@@ -3311,12 +3317,19 @@ public class Vpn {
            // already terminated due to other failures.
            cancelHandleNetworkLostTimeout();

            synchronized (Vpn.this) {
                // Ignore stale runner.
                if (mVpnRunner != this) return;
            String category = null;
            int errorClass = -1;
            int errorCode = -1;
            if (exception instanceof IllegalArgumentException) {
                // Failed to build IKE/ChildSessionParams; fatal profile configuration error
                markFailedAndDisconnect(exception);
                return;
            }

            if (exception instanceof IkeProtocolException) {
                final IkeProtocolException ikeException = (IkeProtocolException) exception;
                category = VpnManager.CATEGORY_EVENT_IKE_ERROR;
                errorCode = ikeException.getErrorType();

                switch (ikeException.getErrorType()) {
                    case IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN: // Fallthrough
@@ -3326,104 +3339,49 @@ public class Vpn {
                    case IkeProtocolException.ERROR_TYPE_FAILED_CP_REQUIRED: // Fallthrough
                    case IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE:
                        // All the above failures are configuration errors, and are terminal
                            // TODO(b/230548427): Remove SDK check once VPN related stuff are
                            //  decoupled from ConnectivityServiceTest.
                            if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) {
                                sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
                                        VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
                                        ikeException.getErrorType(),
                                        getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                        network,
                                        getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                                mUnderlyingNetworkCapabilities),
                                        getRedactedLinkPropertiesOfUnderlyingNetwork(
                                                mUnderlyingLinkProperties));
                            }
                            markFailedAndDisconnect(exception);
                            return;
                        errorClass = VpnManager.ERROR_CLASS_NOT_RECOVERABLE;
                        break;
                    // All other cases possibly recoverable.
                    default:
                            // All the above failures are configuration errors, and are terminal
                            // TODO(b/230548427): Remove SDK check once VPN related stuff are
                            //  decoupled from ConnectivityServiceTest.
                            if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) {
                                sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
                                        VpnManager.ERROR_CLASS_RECOVERABLE,
                                        ikeException.getErrorType(),
                                        getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                        network,
                                        getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                                mUnderlyingNetworkCapabilities),
                                        getRedactedLinkPropertiesOfUnderlyingNetwork(
                                                mUnderlyingLinkProperties));
                            }
                        errorClass = VpnManager.ERROR_CLASS_RECOVERABLE;
                }
                } else if (exception instanceof IllegalArgumentException) {
                    // Failed to build IKE/ChildSessionParams; fatal profile configuration error
                    markFailedAndDisconnect(exception);
                    return;
            } else if (exception instanceof IkeNetworkLostException) {
                    // TODO(b/230548427): Remove SDK check once VPN related stuff are
                    //  decoupled from ConnectivityServiceTest.
                    if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) {
                        sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
                                VpnManager.ERROR_CLASS_RECOVERABLE,
                                VpnManager.ERROR_CODE_NETWORK_LOST,
                                getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                network,
                                getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                        mUnderlyingNetworkCapabilities),
                                getRedactedLinkPropertiesOfUnderlyingNetwork(
                                        mUnderlyingLinkProperties));
                    }
                category = VpnManager.CATEGORY_EVENT_NETWORK_ERROR;
                errorClass = VpnManager.ERROR_CLASS_RECOVERABLE;
                errorCode = VpnManager.ERROR_CODE_NETWORK_LOST;
            } else if (exception instanceof IkeNonProtocolException) {
                category = VpnManager.CATEGORY_EVENT_NETWORK_ERROR;
                errorClass = VpnManager.ERROR_CLASS_RECOVERABLE;
                if (exception.getCause() instanceof UnknownHostException) {
                        // TODO(b/230548427): Remove SDK check once VPN related stuff are
                        //  decoupled from ConnectivityServiceTest.
                        if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) {
                            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
                                    VpnManager.ERROR_CLASS_RECOVERABLE,
                                    VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST,
                                    getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                    network,
                                    getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                            mUnderlyingNetworkCapabilities),
                                    getRedactedLinkPropertiesOfUnderlyingNetwork(
                                            mUnderlyingLinkProperties));
                        }
                    errorCode = VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST;
                } else if (exception.getCause() instanceof IkeTimeoutException) {
                        // TODO(b/230548427): Remove SDK check once VPN related stuff are
                        //  decoupled from ConnectivityServiceTest.
                        if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) {
                            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
                                    VpnManager.ERROR_CLASS_RECOVERABLE,
                                    VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT,
                                    getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                    network,
                                    getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                            mUnderlyingNetworkCapabilities),
                                    getRedactedLinkPropertiesOfUnderlyingNetwork(
                                            mUnderlyingLinkProperties));
                        }
                    errorCode = VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT;
                } else if (exception.getCause() instanceof IOException) {
                    errorCode = VpnManager.ERROR_CODE_NETWORK_IO;
                }
            } else if (exception != null) {
                Log.wtf(TAG, "onSessionLost: exception = " + exception);
            }

            synchronized (Vpn.this) {
                // Ignore stale runner.
                if (mVpnRunner != this) return;

                // TODO(b/230548427): Remove SDK check once VPN related stuff are
                //  decoupled from ConnectivityServiceTest.
                        if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) {
                            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
                                    VpnManager.ERROR_CLASS_RECOVERABLE,
                                    VpnManager.ERROR_CODE_NETWORK_IO,
                if (SdkLevel.isAtLeastT() && category != null && isVpnApp(mPackage)) {
                    sendEventToVpnManagerApp(category, errorClass, errorCode,
                            getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                    network,
                                    getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                            mUnderlyingNetworkCapabilities),
                                    getRedactedLinkPropertiesOfUnderlyingNetwork(
                                            mUnderlyingLinkProperties));
                            mActiveNetwork,
                            getRedactedNetworkCapabilities(mUnderlyingNetworkCapabilities),
                            getRedactedLinkProperties(mUnderlyingLinkProperties));
                }
            }
                } else if (exception != null) {
                    Log.wtf(TAG, "onSessionLost: exception = " + exception);
                }

            if (errorClass == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) {
                markFailedAndDisconnect(exception);
                return;
            } else {
                scheduleRetryNewIkeSession();
            }