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

Commit 839756e6 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Android (Google) Code Review
Browse files

Merge changes from topic "vpnmanager-events-T" into tm-dev

* changes:
  Address leftover comments of ag/18108411
  Address leftover comments of ag/18112116
  Rename vars of Ikev2VpnRunner
  Send VPN manager event when there is a network error
  Send VPN manager event when there is an IkeProtocolException
parents 0d7f8ceb 63b2a309
Loading
Loading
Loading
Loading
+174 −43
Original line number Diff line number Diff line
@@ -88,7 +88,10 @@ import android.net.ipsec.ike.IkeSession;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.net.ipsec.ike.exceptions.IkeNetworkLostException;
import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.ipsec.ike.exceptions.IkeTimeoutException;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
@@ -760,12 +763,20 @@ public class Vpn {
        // Also notify the new package if there was a provider change.
        final boolean shouldNotifyNewPkg = isVpnApp(packageName) && isPackageChanged;

        if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownAllowlist)) {
        if (!setAlwaysOnPackageInternal(packageName, lockdown, lockdownAllowlist)) {
            return false;
        }

        saveAlwaysOnPackage();

        // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
        //  ConnectivityServiceTest.
            if (shouldNotifyOldPkg && SdkLevel.isAtLeastT()) {
                // If both of shouldNotifyOldPkg & isPackageChanged are true, which means the
        if (!SdkLevel.isAtLeastT()) {
            return true;
        }

        if (shouldNotifyOldPkg) {
            // If both of shouldNotifyOldPkg & isPackageChanged are true, that means the
            // always-on of old package is disabled or the old package is replaced with the new
            // package. In this case, VpnProfileState should be disconnected.
            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
@@ -774,9 +785,8 @@ public class Vpn {
                            : makeVpnProfileStateLocked(),
                    null /* underlyingNetwork */, null /* nc */, null /* lp */);
        }
            // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
            //  ConnectivityServiceTest.
            if (shouldNotifyNewPkg && SdkLevel.isAtLeastT()) {

        if (shouldNotifyNewPkg) {
            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
                    -1 /* errorClass */, -1 /* errorCode*/, packageName,
                    getSessionKeyLocked(), makeVpnProfileStateLocked(),
@@ -784,8 +794,6 @@ public class Vpn {
        }
        return true;
    }
        return false;
    }

    /**
     * Configures an always-on VPN connection through a specific application, the same as {@link
@@ -2530,6 +2538,21 @@ public class Vpn {
        }
    }

    @Nullable
    protected synchronized NetworkCapabilities getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
            NetworkCapabilities nc) {
        if (nc == null) return null;
        return mConnectivityManager.getRedactedNetworkCapabilitiesForPackage(
                nc, mOwnerUID, mPackage);
    }

    @Nullable
    protected synchronized LinkProperties getRedactedLinkPropertiesOfUnderlyingNetwork(
            LinkProperties lp) {
        if (lp == null) return null;
        return mConnectivityManager.getRedactedLinkPropertiesForPackage(lp, mOwnerUID, mPackage);
    }

    /** This class represents the common interface for all VPN runners. */
    @VisibleForTesting
    abstract class VpnRunner extends Thread {
@@ -2564,6 +2587,10 @@ public class Vpn {
    interface IkeV2VpnRunnerCallback {
        void onDefaultNetworkChanged(@NonNull Network network);

        void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc);

        void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp);

        void onChildOpened(
                @NonNull Network network, @NonNull ChildSessionConfiguration childConfig);

@@ -2620,14 +2647,14 @@ public class Vpn {
        @Nullable private IpSecTunnelInterface mTunnelIface;
        @Nullable private IkeSession mSession;
        @Nullable private Network mActiveNetwork;
        @Nullable private NetworkCapabilities mUnderlyingNetworkCapabilities;
        @Nullable private LinkProperties mUnderlyingLinkProperties;
        private final String mSessionKey;

        IkeV2VpnRunner(@NonNull Ikev2VpnProfile profile) {
            super(TAG);
            mProfile = profile;
            mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
            // Pass mExecutor into Ikev2VpnNetworkCallback and make sure that IkeV2VpnRunnerCallback
            // will be called by the mExecutor thread.
            mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this, mExecutor);
            mSessionKey = UUID.randomUUID().toString();
        }
@@ -2849,6 +2876,16 @@ public class Vpn {
            }
        }

        /** Called when the NetworkCapabilities of underlying network is changed */
        public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) {
            mUnderlyingNetworkCapabilities = nc;
        }

        /** Called when the LinkProperties of underlying network is changed */
        public void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp) {
            mUnderlyingLinkProperties = lp;
        }

        /** Marks the state as FAILED, and disconnects. */
        private void markFailedAndDisconnect(Exception exception) {
            synchronized (Vpn.this) {
@@ -2879,6 +2916,7 @@ public class Vpn {
                return;
            }

            synchronized (Vpn.this) {
                if (exception instanceof IkeProtocolException) {
                    final IkeProtocolException ikeException = (IkeProtocolException) exception;

@@ -2890,17 +2928,108 @@ 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()) {
                                sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
                                        VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
                                        ikeException.getErrorType(),
                                        getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                        mActiveNetwork,
                                        getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                                mUnderlyingNetworkCapabilities),
                                        getRedactedLinkPropertiesOfUnderlyingNetwork(
                                                mUnderlyingLinkProperties));
                            }
                            markFailedAndDisconnect(exception);
                            return;
                        // 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()) {
                                sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
                                        VpnManager.ERROR_CLASS_RECOVERABLE,
                                        ikeException.getErrorType(),
                                        getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                        mActiveNetwork,
                                        getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                                mUnderlyingNetworkCapabilities),
                                        getRedactedLinkPropertiesOfUnderlyingNetwork(
                                                mUnderlyingLinkProperties));
                            }
                    }
                } 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()) {
                        sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
                                VpnManager.ERROR_CLASS_RECOVERABLE,
                                VpnManager.ERROR_CODE_NETWORK_LOST,
                                getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                mActiveNetwork,
                                getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                        mUnderlyingNetworkCapabilities),
                                getRedactedLinkPropertiesOfUnderlyingNetwork(
                                        mUnderlyingLinkProperties));
                    }
                } else if (exception instanceof IkeNonProtocolException) {
                    if (exception.getCause() instanceof UnknownHostException) {
                        // TODO(b/230548427): Remove SDK check once VPN related stuff are
                        //  decoupled from ConnectivityServiceTest.
                        if (SdkLevel.isAtLeastT()) {
                            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
                                    VpnManager.ERROR_CLASS_RECOVERABLE,
                                    VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST,
                                    getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                    mActiveNetwork,
                                    getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                            mUnderlyingNetworkCapabilities),
                                    getRedactedLinkPropertiesOfUnderlyingNetwork(
                                            mUnderlyingLinkProperties));
                        }
                    } else if (exception.getCause() instanceof IkeTimeoutException) {
                        // TODO(b/230548427): Remove SDK check once VPN related stuff are
                        //  decoupled from ConnectivityServiceTest.
                        if (SdkLevel.isAtLeastT()) {
                            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
                                    VpnManager.ERROR_CLASS_RECOVERABLE,
                                    VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT,
                                    getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                    mActiveNetwork,
                                    getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                            mUnderlyingNetworkCapabilities),
                                    getRedactedLinkPropertiesOfUnderlyingNetwork(
                                            mUnderlyingLinkProperties));
                        }
                    } else if (exception.getCause() instanceof IOException) {
                        // TODO(b/230548427): Remove SDK check once VPN related stuff are
                        //  decoupled from ConnectivityServiceTest.
                        if (SdkLevel.isAtLeastT()) {
                            sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
                                    VpnManager.ERROR_CLASS_RECOVERABLE,
                                    VpnManager.ERROR_CODE_NETWORK_IO,
                                    getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                                    mActiveNetwork,
                                    getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
                                            mUnderlyingNetworkCapabilities),
                                    getRedactedLinkPropertiesOfUnderlyingNetwork(
                                            mUnderlyingLinkProperties));
                        }
                    }
                } else if (exception != null) {
                    Log.wtf(TAG, "onSessionLost: exception = " + exception);
                }
            }

            mActiveNetwork = null;
            mUnderlyingNetworkCapabilities = null;
            mUnderlyingLinkProperties = null;

            // Close all obsolete state, but keep VPN alive incase a usable network comes up.
            // (Mirrors VpnService behavior)
@@ -2965,6 +3094,8 @@ public class Vpn {
         */
        private void disconnectVpnRunner() {
            mActiveNetwork = null;
            mUnderlyingNetworkCapabilities = null;
            mUnderlyingLinkProperties = null;
            mIsRunning = false;

            resetIkeState();
+21 −3
Original line number Diff line number Diff line
@@ -50,7 +50,9 @@ import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.IpSecAlgorithm;
import android.net.IpSecTransform;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.RouteInfo;
import android.net.eap.EapSessionConfig;
import android.net.ipsec.ike.ChildSaProposal;
@@ -86,7 +88,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executor;

/**
 * Utility class to build and convert IKEv2/IPsec parameters.
@@ -377,10 +379,10 @@ public class VpnIkev2Utils {
    static class Ikev2VpnNetworkCallback extends NetworkCallback {
        private final String mTag;
        private final Vpn.IkeV2VpnRunnerCallback mCallback;
        private final ExecutorService mExecutor;
        private final Executor mExecutor;

        Ikev2VpnNetworkCallback(String tag, Vpn.IkeV2VpnRunnerCallback callback,
                ExecutorService executor) {
                Executor executor) {
            mTag = tag;
            mCallback = callback;
            mExecutor = executor;
@@ -392,6 +394,22 @@ public class VpnIkev2Utils {
            mExecutor.execute(() -> mCallback.onDefaultNetworkChanged(network));
        }

        @Override
        public void onCapabilitiesChanged(@NonNull Network network,
                @NonNull NetworkCapabilities networkCapabilities) {
            Log.d(mTag, "NC changed for net " + network + " : " + networkCapabilities);
            mExecutor.execute(
                    () -> mCallback.onDefaultNetworkCapabilitiesChanged(networkCapabilities));
        }

        @Override
        public void onLinkPropertiesChanged(@NonNull Network network,
                @NonNull LinkProperties linkProperties) {
            Log.d(mTag, "LP changed for net " + network + " : " + linkProperties);
            mExecutor.execute(
                    () -> mCallback.onDefaultNetworkLinkPropertiesChanged(linkProperties));
        }

        @Override
        public void onLost(@NonNull Network network) {
            Log.d(mTag, "Tearing down; lost network: " + network);