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

Commit a924d42f authored by Paul Hu's avatar Paul Hu
Browse files

Record VPN underlying network types

Bug: 306313287
Test: atest FrameworksVpnTests
Flag: com.android.server.connectivity.collect_vpn_metrics
Change-Id: I02889e06855e6664c6602891ec8a03421de85fcc
parent 113bef37
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -607,8 +607,9 @@ public class Vpn {
         *
         * <p>This method is only called when {@link collectVpnMetrics} is true.
         */
        public VpnConnectivityMetrics makeVpnConnectivityMetrics(int userId) {
            return new VpnConnectivityMetrics(userId);
        public VpnConnectivityMetrics makeVpnConnectivityMetrics(int userId,
                ConnectivityManager cm) {
            return new VpnConnectivityMetrics(userId, cm);
        }
    }

@@ -666,8 +667,8 @@ public class Vpn {
        mPackage = VpnConfig.LEGACY_VPN;
        mOwnerUID = getAppUid(mContext, mPackage, mUserId);
        mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage);
        mVpnConnectivityMetrics =
                collectVpnMetrics() ? mDeps.makeVpnConnectivityMetrics(userId) : null;
        mVpnConnectivityMetrics = collectVpnMetrics()
                ? mDeps.makeVpnConnectivityMetrics(userId, mConnectivityManager) : null;

        try {
            netService.registerObserver(mObserver);
@@ -2297,6 +2298,15 @@ public class Vpn {
        }
    }

    private void setUnderlyingNetworksAndMetrics(@NonNull Network[] networks) {
        synchronized (Vpn.this) {
            mConfig.underlyingNetworks = networks;
            if (mVpnConnectivityMetrics != null) {
                mVpnConnectivityMetrics.setUnderlyingNetwork(mConfig.underlyingNetworks);
            }
        }
    }

    /**
     * Updates underlying network set.
     */
@@ -3059,7 +3069,7 @@ public class Vpn {
                    mConfig.dnsServers.clear();
                    mConfig.dnsServers.addAll(dnsAddrStrings);

                    mConfig.underlyingNetworks = new Network[] {network};
                    setUnderlyingNetworksAndMetrics(new Network[] {network});

                    networkAgent = mNetworkAgent;

@@ -3152,9 +3162,8 @@ public class Vpn {

                    final LinkProperties oldLp = makeLinkProperties();

                    mConfig.underlyingNetworks = new Network[] {network};
                    setUnderlyingNetworksAndMetrics(new Network[] {network});
                    setMtu(calculateVpnMtu());

                    final LinkProperties newLp = makeLinkProperties();

                    // If MTU is < 1280, IPv6 addresses will be removed. If there are no addresses
+54 −3
Original line number Diff line number Diff line
@@ -28,24 +28,32 @@ import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
import static android.net.IpSecAlgorithm.CRYPT_AES_CTR;

import android.annotation.NonNull;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.VpnManager;
import android.util.Log;
import android.util.SparseArray;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import java.util.Arrays;
import java.util.List;

/**
 * Class to record the VpnConnectionReported into statsd.
 * Class to record the VpnConnectionReported into statsd, facilitating the logging of independent
 * VPN connection details per user.
 */
public class VpnConnectivityMetrics {
    private static final String TAG = VpnConnectivityMetrics.class.getSimpleName();
    public static final int VPN_TYPE_UNKNOWN = 0;
    public static final int VPN_PROFILE_TYPE_UNKNOWN = 0;
    private static final int UNKNOWN_UNDERLYING_NETWORK_TYPE = -1;
    private static final SparseArray<String> sAlgorithms = new SparseArray<>();
    private final int mUserId;
    @NonNull
    private final ConnectivityManager mConnectivityManager;
    private int mVpnType = VPN_TYPE_UNKNOWN;
    private int mVpnProfileType = VPN_PROFILE_TYPE_UNKNOWN;
    private int mMtu = 0;
@@ -56,6 +64,17 @@ public class VpnConnectivityMetrics {
     * index in {@code sAlgorithms} is considered allowed.
     */
    private int mAllowedAlgorithms = 0;
    /**
     * An array representing the transport types of the underlying networks for the VPN.
     * Each element in this array corresponds to a specific underlying network.
     * The value of each element is the primary transport type of the network
     * (e.g., {@link NetworkCapabilities#TRANSPORT_WIFI},
     * {@link NetworkCapabilities#TRANSPORT_CELLULAR}).
     * If the transport type of a network cannot be determined, the value will be
     * {@code UNKNOWN_UNDERLYING_NETWORK_TYPE}.
     */
    @NonNull
    private int[] mUnderlyingNetworkTypes;

    // Static initializer block to populate the sAlgorithms mapping. It associates integer keys
    // (which also serve as bit positions for the mAllowedAlgorithms bitmask) with their
@@ -74,8 +93,9 @@ public class VpnConnectivityMetrics {
        sAlgorithms.put(10, CRYPT_AES_CTR);
    }

    public VpnConnectivityMetrics(int userId) {
    public VpnConnectivityMetrics(int userId, ConnectivityManager connectivityManager) {
        mUserId = userId;
        mConnectivityManager = connectivityManager;
    }

    /**
@@ -146,4 +166,35 @@ public class VpnConnectivityMetrics {
        }
        return bitmask;
    }

    /**
     * Sets the transport types of the underlying networks for the VPN.
     * <p>
     * This method processes an array of {@link android.net.Network} objects. For each network,
     * it attempts to retrieve its {@link android.net.NetworkCapabilities} and extracts the
     * primary transport type (e.g., Wi-Fi, cellular). If capabilities cannot be retrieved
     * for a specific network, a predefined {@code UNKNOWN_UNDERLYING_NETWORK_TYPE} is
     * used for that entry.
     *
     * @param networks An array of {@link android.net.Network} objects representing the underlying
     *                 networks currently in use.
     */
    public void setUnderlyingNetwork(@NonNull Network[] networks) {
        if (networks.length != 0) {
            int[] types = new int[networks.length];
            for (int i = 0; i < networks.length; i++) {
                final NetworkCapabilities capabilities =
                        mConnectivityManager.getNetworkCapabilities(networks[i]);
                if (capabilities != null) {
                    // Get the primary transport type of the network.
                    types[i] = capabilities.getTransportTypes()[0];
                } else {
                    types[i] = UNKNOWN_UNDERLYING_NETWORK_TYPE;
                }
            }
            mUnderlyingNetworkTypes = Arrays.copyOf(types, types.length);
        } else {
            mUnderlyingNetworkTypes = new int[0];
        }
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -3293,7 +3293,8 @@ public class VpnTest extends VpnTestBase {
        }

        @Override
        public VpnConnectivityMetrics makeVpnConnectivityMetrics(int userId) {
        public VpnConnectivityMetrics makeVpnConnectivityMetrics(int userId,
                ConnectivityManager cm) {
            return mVpnConnectivityMetrics;
        }
    }