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

Commit f5ea340a authored by Wenchao Tong's avatar Wenchao Tong
Browse files

NetworkStatsService to adjust VPN stats before recording.

* Creates a new Parcelable class VpnInfo to hold required
  parameters for VPN stats adjustments.
* ConnectivityService to collect infomation and provide
  a list of VpnInfo, one for each user.
* NetworkStatsService passes the VpnInfo array to
  NetworkStatsRecorder.
* NetworkStatsRecorder calls NetworkStats.migrateTun()
  to do the math.
* Poll NetworkStats when the vpn application calls
  setUnderlyingNetworks().

Bug: 19536273
Change-Id: I7a4c7726b8243fead10416f7ec6eb5cf95f20183
parent d58617b4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.ResultReceiver;

import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;

/**
@@ -116,6 +117,8 @@ interface IConnectivityManager

    LegacyVpnInfo getLegacyVpnInfo();

    VpnInfo[] getAllVpnInfo();

    boolean updateLockdownVpn();

    void captivePortalCheckCompleted(in NetworkInfo info, boolean isCaptivePortal);
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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 com.android.internal.net;

parcelable VpnInfo;
+69 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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 com.android.internal.net;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * A lightweight container used to carry information of the ongoing VPN.
 * Internal use only..
 *
 * @hide
 */
public class VpnInfo implements Parcelable {
    public int ownerUid;
    public String vpnIface;
    public String primaryUnderlyingIface;

    @Override
    public String toString() {
        return "VpnInfo{" +
                "ownerUid=" + ownerUid +
                ", vpnIface='" + vpnIface + '\'' +
                ", primaryUnderlyingIface='" + primaryUnderlyingIface + '\'' +
                '}';
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(ownerUid);
        dest.writeString(vpnIface);
        dest.writeString(primaryUnderlyingIface);
    }

    public static final Parcelable.Creator<VpnInfo> CREATOR = new Parcelable.Creator<VpnInfo>() {
        @Override
        public VpnInfo createFromParcel(Parcel source) {
            VpnInfo info = new VpnInfo();
            info.ownerUid = source.readInt();
            info.vpnIface = source.readString();
            info.primaryUnderlyingIface = source.readString();
            return info;
        }

        @Override
        public VpnInfo[] newArray(int size) {
            return new VpnInfo[size];
        }
    };
}
+58 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;

import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -100,6 +101,7 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
import com.android.internal.telephony.DctConstants;
import com.android.internal.util.AsyncChannel;
@@ -2978,7 +2980,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
     * Return the information of the ongoing legacy VPN. This method is used
     * by VpnSettings and not available in ConnectivityManager. Permissions
     * are checked in Vpn class.
     * @hide
     */
    @Override
    public LegacyVpnInfo getLegacyVpnInfo() {
@@ -2989,6 +2990,56 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }
    }

    /**
     * Return the information of all ongoing VPNs. This method is used by NetworkStatsService
     * and not available in ConnectivityManager.
     */
    @Override
    public VpnInfo[] getAllVpnInfo() {
        enforceConnectivityInternalPermission();
        if (mLockdownEnabled) {
            return new VpnInfo[0];
        }

        synchronized(mVpns) {
            List<VpnInfo> infoList = new ArrayList<>();
            for (int i = 0; i < mVpns.size(); i++) {
                VpnInfo info = createVpnInfo(mVpns.valueAt(i));
                if (info != null) {
                    infoList.add(info);
                }
            }
            return infoList.toArray(new VpnInfo[infoList.size()]);
        }
    }

    /**
     * @return VPN information for accounting, or null if we can't retrieve all required
     *         information, e.g primary underlying iface.
     */
    @Nullable
    private VpnInfo createVpnInfo(Vpn vpn) {
        VpnInfo info = vpn.getVpnInfo();
        if (info == null) {
            return null;
        }
        Network[] underlyingNetworks = vpn.getUnderlyingNetworks();
        // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
        // the underlyingNetworks list.
        if (underlyingNetworks == null) {
            NetworkAgentInfo defaultNetwork = getDefaultNetwork();
            if (defaultNetwork != null && defaultNetwork.linkProperties != null) {
                info.primaryUnderlyingIface = getDefaultNetwork().linkProperties.getInterfaceName();
            }
        } else if (underlyingNetworks.length > 0) {
            LinkProperties linkProperties = getLinkProperties(underlyingNetworks[0]);
            if (linkProperties != null) {
                info.primaryUnderlyingIface = linkProperties.getInterfaceName();
            }
        }
        return info.primaryUnderlyingIface == null ? null : info;
    }

    /**
     * Returns the information of the ongoing VPN. This method is used by VpnDialogs and
     * not available in ConnectivityManager.
@@ -4512,8 +4563,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
    public boolean setUnderlyingNetworksForVpn(Network[] networks) {
        throwIfLockdownEnabled();
        int user = UserHandle.getUserId(Binder.getCallingUid());
        boolean success;
        synchronized (mVpns) {
            return mVpns.get(user).setUnderlyingNetworks(networks);
            success = mVpns.get(user).setUnderlyingNetworks(networks);
        }
        if (success) {
            notifyIfacesChanged();
        }
        return success;
    }
}
+16 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
import com.android.server.net.BaseNetworkObserver;

@@ -808,6 +809,21 @@ public class Vpn {
        return mConfig.underlyingNetworks;
    }

    /**
     * This method should only be called by ConnectivityService. Because it doesn't
     * have enough data to fill VpnInfo.primaryUnderlyingIface field.
     */
    public synchronized VpnInfo getVpnInfo() {
        if (!isRunningLocked()) {
            return null;
        }

        VpnInfo info = new VpnInfo();
        info.ownerUid = mOwnerUID;
        info.vpnIface = mInterface;
        return info;
    }

    public synchronized boolean appliesToUid(int uid) {
        if (!isRunningLocked()) {
            return false;
Loading