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

Commit 76e8a43e authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

Add a VpnTransportInfo object.

This currently stores the VPN type and a session name, but can be
extended in the future.

Bug: 173331190
Test: added coverage in VpnTest
Test: added coverage in ConnectivityServiceTest
Test: added coverage in NetworkAgentTest
Change-Id: I450858a9fa332c8d896dbdb4c14337d5ec23677f
parent 20987c31
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;

import com.android.internal.util.MessageUtils;

import java.util.Objects;

/** @hide */
public final class VpnTransportInfo implements TransportInfo, Parcelable {
    private static final SparseArray<String> sTypeToString =
            MessageUtils.findMessageNames(new Class[]{VpnManager.class}, new String[]{"TYPE_VPN_"});

    /** Type of this VPN. */
    @VpnManager.VpnType public final int type;

    public VpnTransportInfo(@VpnManager.VpnType int type) {
        this.type = type;
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof VpnTransportInfo)) return false;

        VpnTransportInfo that = (VpnTransportInfo) o;
        return this.type == that.type;
    }

    @Override
    public int hashCode() {
        return Objects.hash(type);
    }

    @Override
    public String toString() {
        final String typeString = sTypeToString.get(type, "VPN_TYPE_???");
        return String.format("VpnTransportInfo{%s}", typeString);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(type);
    }

    public static final @NonNull Creator<VpnTransportInfo> CREATOR =
            new Creator<VpnTransportInfo>() {
        public VpnTransportInfo createFromParcel(Parcel in) {
            return new VpnTransportInfo(in.readInt());
        }
        public VpnTransportInfo[] newArray(int size) {
            return new VpnTransportInfo[size];
        }
    };
}
+2 −0
Original line number Diff line number Diff line
@@ -762,12 +762,14 @@ public final class NetworkCapabilities implements Parcelable {
        final int originalSignalStrength = mSignalStrength;
        final int originalOwnerUid = getOwnerUid();
        final int[] originalAdministratorUids = getAdministratorUids();
        final TransportInfo originalTransportInfo = getTransportInfo();
        clearAll();
        mTransportTypes = (originalTransportTypes & TEST_NETWORKS_ALLOWED_TRANSPORTS)
                | (1 << TRANSPORT_TEST);
        mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES;
        mNetworkSpecifier = originalSpecifier;
        mSignalStrength = originalSignalStrength;
        mTransportInfo = originalTransportInfo;

        // Only retain the owner and administrator UIDs if they match the app registering the remote
        // caller that registered the network.
+19 −3
Original line number Diff line number Diff line
@@ -55,13 +55,29 @@ import java.security.GeneralSecurityException;
public class VpnManager {
    /** Type representing a lack of VPN @hide */
    public static final int TYPE_VPN_NONE = -1;
    /** VPN service type code @hide */

    /**
     * A VPN created by an app using the {@link VpnService} API.
     * @hide
     */
    public static final int TYPE_VPN_SERVICE = 1;
    /** Platform VPN type code @hide */

    /**
     * A VPN created using a {@link VpnManager} API such as {@link #startProvisionedVpnProfile}.
     * @hide
     */
    public static final int TYPE_VPN_PLATFORM = 2;

    /**
     * An IPsec VPN created by the built-in LegacyVpnRunner.
     * @deprecated new Android devices should use VPN_TYPE_PLATFORM instead.
     * @hide
     */
    @Deprecated
    public static final int TYPE_VPN_LEGACY = 3;

    /** @hide */
    @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM})
    @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY})
    @Retention(RetentionPolicy.SOURCE)
    public @interface VpnType {}

+1 −1
Original line number Diff line number Diff line
@@ -8505,7 +8505,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        final Vpn vpn = enforceActiveVpnOrNetworkStackPermission();

        // Only VpnService based VPNs should be able to get this information.
        if (vpn != null && vpn.getActiveAppVpnType() != VpnManager.TYPE_VPN_SERVICE) {
        if (vpn != null && vpn.getActiveVpnType() != VpnManager.TYPE_VPN_SERVICE) {
            throw new SecurityException(
                    "getConnectionOwnerUid() not allowed for non-VpnService VPNs");
        }
+19 −13
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ import android.net.UidRangeParcel;
import android.net.UnderlyingNetworkInfo;
import android.net.VpnManager;
import android.net.VpnService;
import android.net.VpnTransportInfo;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionConfiguration;
import android.net.ipsec.ike.ChildSessionParams;
@@ -435,6 +436,7 @@ public class Vpn {
        mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
        mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
        mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE));

        loadAlwaysOnPackage(keyStore);
    }
@@ -929,6 +931,7 @@ public class Vpn {
                jniReset(mInterface);
                mInterface = null;
                mNetworkCapabilities.setUids(null);
                mNetworkCapabilities.setTransportInfo(null);
            }

            // Revoke the connection or stop the VpnRunner.
@@ -999,6 +1002,8 @@ public class Vpn {
                case VpnManager.TYPE_VPN_SERVICE:
                    toChange = new String[] {AppOpsManager.OPSTR_ACTIVATE_VPN};
                    break;
                case VpnManager.TYPE_VPN_LEGACY:
                    return false;
                default:
                    Log.wtf(TAG, "Unrecognized VPN type while granting authorization");
                    return false;
@@ -1029,6 +1034,8 @@ public class Vpn {
                return isVpnServicePreConsented(context, packageName);
            case VpnManager.TYPE_VPN_PLATFORM:
                return isVpnProfilePreConsented(context, packageName);
            case VpnManager.TYPE_VPN_LEGACY:
                return VpnConfig.LEGACY_VPN.equals(packageName);
            default:
                return false;
        }
@@ -1211,6 +1218,8 @@ public class Vpn {
        mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserId,
                mConfig.allowedApplications, mConfig.disallowedApplications));

        mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));

        // Only apps targeting Q and above can explicitly declare themselves as metered.
        // These VPNs are assumed metered unless they state otherwise.
        if (mIsPackageTargetingAtLeastQ && mConfig.isMetered) {
@@ -1736,6 +1745,7 @@ public class Vpn {
    private void cleanupVpnStateLocked() {
        mStatusIntent = null;
        mNetworkCapabilities.setUids(null);
        mNetworkCapabilities.setTransportInfo(null);
        mConfig = null;
        mInterface = null;

@@ -1846,22 +1856,18 @@ public class Vpn {
    }

    /**
     * Gets the currently running App-based VPN type
     * Gets the currently running VPN type
     *
     * @return the {@link VpnManager.VpnType}. {@link VpnManager.TYPE_VPN_NONE} if not running an
     *     app-based VPN. While VpnService-based VPNs are always app VPNs and LegacyVpn is always
     * @return the {@link VpnManager.VpnType}. {@link VpnManager.TYPE_VPN_NONE} if not running a
     *     VPN. While VpnService-based VPNs are always app VPNs and LegacyVpn is always
     *     Settings-based, the Platform VPNs can be initiated by both apps and Settings.
     */
    public synchronized int getActiveAppVpnType() {
        if (VpnConfig.LEGACY_VPN.equals(mPackage)) {
            return VpnManager.TYPE_VPN_NONE;
        }

        if (mVpnRunner != null && mVpnRunner instanceof IkeV2VpnRunner) {
            return VpnManager.TYPE_VPN_PLATFORM;
        } else {
            return VpnManager.TYPE_VPN_SERVICE;
        }
    public synchronized int getActiveVpnType() {
        if (!mNetworkInfo.isConnectedOrConnecting()) return VpnManager.TYPE_VPN_NONE;
        if (mVpnRunner == null) return VpnManager.TYPE_VPN_SERVICE;
        return mVpnRunner instanceof IkeV2VpnRunner
                ? VpnManager.TYPE_VPN_PLATFORM
                : VpnManager.TYPE_VPN_LEGACY;
    }

    private void updateAlwaysOnNotification(DetailedState networkState) {
Loading