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

Commit 6f5a8db2 authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN Committed by Android (Google) Code Review
Browse files

Merge "Add method to NetworkStatsService for UID stats." into pi-dev

parents dfa8f0db b6a92012
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -41,6 +41,16 @@ interface INetworkStatsService {

    /** Return data layer snapshot of UID network usage. */
    NetworkStats getDataLayerSnapshotForUid(int uid);

    /** Get a detailed snapshot of stats since boot for all UIDs.
    *
    * <p>Results will not always be limited to stats on requiredIfaces when specified: stats for
    * interfaces stacked on the specified interfaces, or for interfaces on which the specified
    * interfaces are stacked on, will also be included.
    * @param requiredIfaces Interface names to get data for, or {@link NetworkStats#INTERFACES_ALL}.
    */
    NetworkStats getDetailedUidStats(in String[] requiredIfaces);

    /** Return set of any ifaces associated with mobile networks since boot. */
    String[] getMobileIfaces();

+52 −12
Original line number Diff line number Diff line
@@ -64,6 +64,9 @@ public class NetworkStats implements Parcelable {
    /** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */
    public static final int SET_DBG_VPN_OUT = 1002;

    /** Include all interfaces when filtering */
    public static final String[] INTERFACES_ALL = null;

    /** {@link #tag} value for total data across all tags. */
    // TODO: Rename TAG_NONE to TAG_ALL.
    public static final int TAG_NONE = 0;
@@ -366,23 +369,27 @@ public class NetworkStats implements Parcelable {
            capacity = newLength;
        }

        iface[size] = entry.iface;
        uid[size] = entry.uid;
        set[size] = entry.set;
        tag[size] = entry.tag;
        metered[size] = entry.metered;
        roaming[size] = entry.roaming;
        defaultNetwork[size] = entry.defaultNetwork;
        rxBytes[size] = entry.rxBytes;
        rxPackets[size] = entry.rxPackets;
        txBytes[size] = entry.txBytes;
        txPackets[size] = entry.txPackets;
        operations[size] = entry.operations;
        setValues(size, entry);
        size++;

        return this;
    }

    private void setValues(int i, Entry entry) {
        iface[i] = entry.iface;
        uid[i] = entry.uid;
        set[i] = entry.set;
        tag[i] = entry.tag;
        metered[i] = entry.metered;
        roaming[i] = entry.roaming;
        defaultNetwork[i] = entry.defaultNetwork;
        rxBytes[i] = entry.rxBytes;
        rxPackets[i] = entry.rxPackets;
        txBytes[i] = entry.txBytes;
        txPackets[i] = entry.txPackets;
        operations[i] = entry.operations;
    }

    /**
     * Return specific stats entry.
     */
@@ -831,6 +838,39 @@ public class NetworkStats implements Parcelable {
        return stats;
    }

    /**
     * Only keep entries that match all specified filters.
     *
     * <p>This mutates the original structure in place. After this method is called,
     * size is the number of matching entries, and capacity is the previous capacity.
     * @param limitUid UID to filter for, or {@link #UID_ALL}.
     * @param limitIfaces Interfaces to filter for, or {@link #INTERFACES_ALL}.
     * @param limitTag Tag to filter for, or {@link #TAG_ALL}.
     */
    public void filter(int limitUid, String[] limitIfaces, int limitTag) {
        if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
            return;
        }

        Entry entry = new Entry();
        int nextOutputEntry = 0;
        for (int i = 0; i < size; i++) {
            entry = getValues(i, entry);
            final boolean matches =
                    (limitUid == UID_ALL || limitUid == entry.uid)
                    && (limitTag == TAG_ALL || limitTag == entry.tag)
                    && (limitIfaces == INTERFACES_ALL
                            || ArrayUtils.contains(limitIfaces, entry.iface));

            if (matches) {
                setValues(nextOutputEntry, entry);
                nextOutputEntry++;
            }
        }

        size = nextOutputEntry;
    }

    public void dump(String prefix, PrintWriter pw) {
        pw.print(prefix);
        pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
+4 −2
Original line number Diff line number Diff line
@@ -268,10 +268,12 @@ interface INetworkManagementService
    NetworkStats getNetworkStatsDetail();

    /**
     * Return detailed network statistics for the requested UID,
     * Return detailed network statistics for the requested UID and interfaces,
     * including interface and tag details.
     * @param uid UID to obtain statistics for, or {@link NetworkStats#UID_ALL}.
     * @param ifaces Interfaces to obtain statistics for, or {@link NetworkStats#INTERFACES_ALL}.
     */
    NetworkStats getNetworkStatsUidDetail(int uid);
    NetworkStats getNetworkStatsUidDetail(int uid, in String[] ifaces);

    /**
     * Return summary of network statistics all tethering interfaces.
+53 −19
Original line number Diff line number Diff line
@@ -22,16 +22,14 @@ import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;

import android.annotation.Nullable;
import android.net.NetworkStats;
import android.os.StrictMode;
import android.os.SystemClock;
import android.util.ArrayMap;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ProcFileReader;
import com.google.android.collect.Lists;

import libcore.io.IoUtils;

@@ -41,8 +39,10 @@ import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Creates {@link NetworkStats} instances by parsing various {@code /proc/}
@@ -72,18 +72,55 @@ public class NetworkStatsFactory {

    private boolean mUseBpfStats;

    // TODO: to improve testability and avoid global state, do not use a static variable.
    @GuardedBy("sStackedIfaces")
    private static final ArrayMap<String, String> sStackedIfaces = new ArrayMap<>();
    // TODO: only do adjustments in NetworkStatsService and remove this.
    /**
     * (Stacked interface) -> (base interface) association for all connected ifaces since boot.
     *
     * Because counters must never roll backwards, once a given interface is stacked on top of an
     * underlying interface, the stacked interface can never be stacked on top of
     * another interface. */
    private static final ConcurrentHashMap<String, String> sStackedIfaces
            = new ConcurrentHashMap<>();

    public static void noteStackedIface(String stackedIface, String baseIface) {
        synchronized (sStackedIfaces) {
            if (baseIface != null) {
        if (stackedIface != null && baseIface != null) {
            sStackedIfaces.put(stackedIface, baseIface);
            } else {
                sStackedIfaces.remove(stackedIface);
        }
    }

    /**
     * Get a set of interfaces containing specified ifaces and stacked interfaces.
     *
     * <p>The added stacked interfaces are ifaces stacked on top of the specified ones, or ifaces
     * on which the specified ones are stacked. Stacked interfaces are those noted with
     * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method
     * is called are guaranteed to be included.
     */
    public static String[] augmentWithStackedInterfacesLocked(@Nullable String[] requiredIfaces) {
        if (requiredIfaces == NetworkStats.INTERFACES_ALL) {
            return null;
        }

        HashSet<String> relatedIfaces = new HashSet<>(Arrays.asList(requiredIfaces));
        // ConcurrentHashMap's EntrySet iterators are "guaranteed to traverse
        // elements as they existed upon construction exactly once, and may
        // (but are not guaranteed to) reflect any modifications subsequent to construction".
        // This is enough here.
        for (Map.Entry<String, String> entry : sStackedIfaces.entrySet()) {
            if (relatedIfaces.contains(entry.getKey())) {
                relatedIfaces.add(entry.getValue());
            } else if (relatedIfaces.contains(entry.getValue())) {
                relatedIfaces.add(entry.getKey());
            }
        }

        String[] outArray = new String[relatedIfaces.size()];
        return relatedIfaces.toArray(outArray);
    }

    @VisibleForTesting
    public static void clearStackedIfaces() {
        sStackedIfaces.clear();
    }

    public NetworkStatsFactory() {
@@ -252,12 +289,9 @@ public class NetworkStatsFactory {
            NetworkStats lastStats) throws IOException {
        final NetworkStats stats =
              readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats);
        final ArrayMap<String, String> stackedIfaces;
        synchronized (sStackedIfaces) {
            stackedIfaces = new ArrayMap<>(sStackedIfaces);
        }
        // Total 464xlat traffic to subtract from uid 0 on all base interfaces.
        final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size());
        // sStackedIfaces may grow afterwards, but NetworkStats will just be resized automatically.
        final NetworkStats adjustments = new NetworkStats(0, sStackedIfaces.size());

        NetworkStats.Entry entry = null; // For recycling

@@ -271,7 +305,7 @@ public class NetworkStatsFactory {
            if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) {
                continue;
            }
            final String baseIface = stackedIfaces.get(entry.iface);
            final String baseIface = sStackedIfaces.get(entry.iface);
            if (baseIface == null) {
                continue;
            }
+0 −1
Original line number Diff line number Diff line
@@ -5320,7 +5320,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
                for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) {
                    final String stackedIface = stacked.getInterfaceName();
                    bs.noteNetworkInterfaceType(stackedIface, type);
                    NetworkStatsFactory.noteStackedIface(stackedIface, baseIface);
                }
            } catch (RemoteException ignored) {
            }
Loading