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

Commit e8914c36 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Begin collecting xtables iface counters.

Add method to parse new iface_stat_fmt proc stats, or return null
when kernel support is unavailable. Add test and remove older, unused
parsing code. Create new "xt" recorder to persist the new xtables
counters when available.

Add SSID support to NetworkIdentity to fix policy tests.

Bug: 6422414
Change-Id: I77f70e9acb79a559ab626f3af5c4f3599801ed43
parent f2dc6fc4
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -158,10 +158,15 @@ public class NetworkIdentity {
            }

        } else if (type == TYPE_WIFI) {
            final WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            if (state.networkId != null) {
                networkId = state.networkId;
            } else {
                final WifiManager wifi = (WifiManager) context.getSystemService(
                        Context.WIFI_SERVICE);
                final WifiInfo info = wifi.getConnectionInfo();
                networkId = info != null ? info.getSSID() : null;
            }
        }

        return new NetworkIdentity(type, subType, subscriberId, networkId, roaming);
    }
+6 −2
Original line number Diff line number Diff line
@@ -31,18 +31,20 @@ public class NetworkState implements Parcelable {
    public final LinkCapabilities linkCapabilities;
    /** Currently only used by testing. */
    public final String subscriberId;
    public final String networkId;

    public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
            LinkCapabilities linkCapabilities) {
        this(networkInfo, linkProperties, linkCapabilities, null);
        this(networkInfo, linkProperties, linkCapabilities, null, null);
    }

    public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
            LinkCapabilities linkCapabilities, String subscriberId) {
            LinkCapabilities linkCapabilities, String subscriberId, String networkId) {
        this.networkInfo = networkInfo;
        this.linkProperties = linkProperties;
        this.linkCapabilities = linkCapabilities;
        this.subscriberId = subscriberId;
        this.networkId = networkId;
    }

    public NetworkState(Parcel in) {
@@ -50,6 +52,7 @@ public class NetworkState implements Parcelable {
        linkProperties = in.readParcelable(null);
        linkCapabilities = in.readParcelable(null);
        subscriberId = in.readString();
        networkId = in.readString();
    }

    @Override
@@ -63,6 +66,7 @@ public class NetworkState implements Parcelable {
        out.writeParcelable(linkProperties, flags);
        out.writeParcelable(linkCapabilities, flags);
        out.writeString(subscriberId);
        out.writeString(networkId);
    }

    public static final Creator<NetworkState> CREATOR = new Creator<NetworkState>() {
+2 −1
Original line number Diff line number Diff line
@@ -238,7 +238,8 @@ interface INetworkManagementService
     * Return global network statistics summarized at an interface level,
     * without any UID-level granularity.
     */
    NetworkStats getNetworkStatsSummary();
    NetworkStats getNetworkStatsSummaryDev();
    NetworkStats getNetworkStatsSummaryXt();

    /**
     * Return detailed network statistics with UID-level granularity,
+34 −131
Original line number Diff line number Diff line
@@ -24,20 +24,12 @@ import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
import android.net.NetworkStats;
import android.os.StrictMode;
import android.os.SystemClock;
import android.util.Slog;

import com.android.internal.util.ProcFileReader;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.StringTokenizer;

import libcore.io.IoUtils;

@@ -50,14 +42,10 @@ public class NetworkStatsFactory {

    // TODO: consider moving parsing to native code

    /** Path to {@code /proc/net/dev}. */
    @Deprecated
    private final File mStatsIface;
    /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
    @Deprecated
    private final File mStatsXtIface;
    /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
    private final File mStatsXtIfaceAll;
    /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
    private final File mStatsXtIfaceFmt;
    /** Path to {@code /proc/net/xt_qtaguid/stats}. */
    private final File mStatsXtUid;

@@ -67,28 +55,20 @@ public class NetworkStatsFactory {

    // @VisibleForTesting
    public NetworkStatsFactory(File procRoot) {
        mStatsIface = new File(procRoot, "net/dev");
        mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
        mStatsXtIface = new File(procRoot, "net/xt_qtaguid/iface_stat");
        mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
        mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
        mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
    }

    /**
     * Parse and return interface-level summary {@link NetworkStats}. Values
     * monotonically increase since device boot, and may include details about
     * inactive interfaces.
     * Parse and return interface-level summary {@link NetworkStats} measured
     * using {@code /proc/net/dev} style hooks, which may include non IP layer
     * traffic. Values monotonically increase since device boot, and may include
     * details about inactive interfaces.
     *
     * @throws IllegalStateException when problem parsing stats.
     */
    public NetworkStats readNetworkStatsSummary() throws IllegalStateException {
        if (mStatsXtIfaceAll.exists()) {
            return readNetworkStatsSummarySingleFile();
        } else {
            return readNetworkStatsSummaryMultipleFiles();
        }
    }

    private NetworkStats readNetworkStatsSummarySingleFile() {
    public NetworkStats readNetworkStatsSummaryDev() throws IllegalStateException {
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();

        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
@@ -137,79 +117,40 @@ public class NetworkStatsFactory {
    }

    /**
     * @deprecated remove once {@code iface_stat_all} is merged to all kernels.
     * Parse and return interface-level summary {@link NetworkStats}. Designed
     * to return only IP layer traffic. Values monotonically increase since
     * device boot, and may include details about inactive interfaces.
     *
     * @throws IllegalStateException when problem parsing stats.
     */
    @Deprecated
    private NetworkStats readNetworkStatsSummaryMultipleFiles() {
    public NetworkStats readNetworkStatsSummaryXt() throws IllegalStateException {
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();

        // return null when kernel doesn't support
        if (!mStatsXtIfaceFmt.exists()) return null;

        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
        final NetworkStats.Entry entry = new NetworkStats.Entry();

        final HashSet<String> knownIfaces = Sets.newHashSet();
        final HashSet<String> activeIfaces = Sets.newHashSet();

        // collect any historical stats and active state
        for (String iface : fileListWithoutNull(mStatsXtIface)) {
            final File ifacePath = new File(mStatsXtIface, iface);

            final long active = readSingleLongFromFile(new File(ifacePath, "active"));
            if (active == 1) {
                knownIfaces.add(iface);
                activeIfaces.add(iface);
            } else if (active == 0) {
                knownIfaces.add(iface);
            } else {
                continue;
            }
        ProcFileReader reader = null;
        try {
            // open and consume header line
            reader = new ProcFileReader(new FileInputStream(mStatsXtIfaceFmt));
            reader.finishLine();

            entry.iface = iface;
            while (reader.hasMoreData()) {
                entry.iface = reader.nextString();
                entry.uid = UID_ALL;
                entry.set = SET_ALL;
                entry.tag = TAG_NONE;
            entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
            entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
            entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
            entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));

            stats.addValues(entry);
        }

        final ArrayList<String> values = Lists.newArrayList();

        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(mStatsIface));

            // skip first two header lines
            reader.readLine();
            reader.readLine();

            // parse remaining lines
            String line;
            while ((line = reader.readLine()) != null) {
                splitLine(line, values);
                entry.rxBytes = reader.nextLong();
                entry.rxPackets = reader.nextLong();
                entry.txBytes = reader.nextLong();
                entry.txPackets = reader.nextLong();

                try {
                    entry.iface = values.get(0);
                    entry.uid = UID_ALL;
                    entry.set = SET_ALL;
                    entry.tag = TAG_NONE;
                    entry.rxBytes = Long.parseLong(values.get(1));
                    entry.rxPackets = Long.parseLong(values.get(2));
                    entry.txBytes = Long.parseLong(values.get(9));
                    entry.txPackets = Long.parseLong(values.get(10));

                    if (activeIfaces.contains(entry.iface)) {
                        // combine stats when iface is active
                        stats.combineValues(entry);
                    } else if (!knownIfaces.contains(entry.iface)) {
                        // add stats when iface is unknown
                stats.addValues(entry);
                    }
                } catch (NumberFormatException e) {
                    Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
                }
                reader.finishLine();
            }
        } catch (NullPointerException e) {
            throw new IllegalStateException("problem parsing stats: " + e);
@@ -221,7 +162,6 @@ public class NetworkStatsFactory {
            IoUtils.closeQuietly(reader);
            StrictMode.setThreadPolicy(savedPolicy);
        }

        return stats;
    }

@@ -286,41 +226,4 @@ public class NetworkStatsFactory {

        return stats;
    }

    /**
     * Split given line into {@link ArrayList}.
     */
    @Deprecated
    private static void splitLine(String line, ArrayList<String> outSplit) {
        outSplit.clear();

        final StringTokenizer t = new StringTokenizer(line, " \t\n\r\f:");
        while (t.hasMoreTokens()) {
            outSplit.add(t.nextToken());
        }
    }

    /**
     * Utility method to read a single plain-text {@link Long} from the given
     * {@link File}, usually from a {@code /proc/} filesystem.
     */
    private static long readSingleLongFromFile(File file) {
        try {
            final byte[] buffer = IoUtils.readFileAsByteArray(file.toString());
            return Long.parseLong(new String(buffer).trim());
        } catch (NumberFormatException e) {
            return -1;
        } catch (IOException e) {
            return -1;
        }
    }

    /**
     * Wrapper for {@link File#list()} that returns empty array instead of
     * {@code null}.
     */
    private static String[] fileListWithoutNull(File file) {
        final String[] list = file.list();
        return list != null ? list : new String[0];
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -5719,7 +5719,7 @@ public final class BatteryStatsImpl extends BatteryStats {

                if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
                    try {
                        mNetworkSummaryCache = mNetworkStatsFactory.readNetworkStatsSummary();
                        mNetworkSummaryCache = mNetworkStatsFactory.readNetworkStatsSummaryDev();
                    } catch (IllegalStateException e) {
                        Log.wtf(TAG, "problem reading network stats", e);
                    }
Loading