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

Commit 98170b0d authored by Wenchao Tong's avatar Wenchao Tong
Browse files

Keep debug information in NetworkStats files

Create two special SETs.

SET_DBG_VPN_IN is used by individual applications to know
how much traffic of the NetworkIdentity was actually moved
from a VPN app.
SET_DBG_VPN_OUT is used by the VPN app to know how much
traffic of the NetworkIdentity was deducted.

A debug application can restore the raw stats by these
entries.
  raw_traffic = recorded_entry (TAG_NONE, SET_ALL)
              + recorded_entry (TAG_NONE, SET_DBF_VPN_OUT)
              - recorded_entry (TAG_NONE, SET_DBF_VPN_IN)

The two debug SETs are not returned by
NetworkStatsService.openSession(). These debug entries are
retrieved by NetworkStatsCollection.dump().

Bug: 19536273
Change-Id: I03ef9f7667f5f2f48cbe3f6b11447fe7ead8ad3b
parent 041ca26d
Loading
Loading
Loading
Loading
+40 −1
Original line number Diff line number Diff line
@@ -50,12 +50,19 @@ public class NetworkStats implements Parcelable {
    public static final int UID_ALL = -1;
    /** {@link #tag} value matching any tag. */
    public static final int TAG_ALL = -1;
    /** {@link #set} value when all sets combined. */
    /** {@link #set} value when all sets combined, not including debug sets. */
    public static final int SET_ALL = -1;
    /** {@link #set} value where background data is accounted. */
    public static final int SET_DEFAULT = 0;
    /** {@link #set} value where foreground data is accounted. */
    public static final int SET_FOREGROUND = 1;
    /** All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values. */
    public static final int SET_DEBUG_START = 1000;
    /** Debug {@link #set} value when the VPN stats are moved in. */
    public static final int SET_DBG_VPN_IN = 1001;
    /** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */
    public static final int SET_DBG_VPN_OUT = 1002;

    /** {@link #tag} value for total data across all tags. */
    public static final int TAG_NONE = 0;

@@ -729,6 +736,10 @@ public class NetworkStats implements Parcelable {
                return "DEFAULT";
            case SET_FOREGROUND:
                return "FOREGROUND";
            case SET_DBG_VPN_IN:
                return "DBG_VPN_IN";
            case SET_DBG_VPN_OUT:
                return "DBG_VPN_OUT";
            default:
                return "UNKNOWN";
        }
@@ -745,11 +756,26 @@ public class NetworkStats implements Parcelable {
                return "def";
            case SET_FOREGROUND:
                return "fg";
            case SET_DBG_VPN_IN:
                return "vpnin";
            case SET_DBG_VPN_OUT:
                return "vpnout";
            default:
                return "unk";
        }
    }

    /**
     * @return true if the querySet matches the dataSet.
     */
    public static boolean setMatches(int querySet, int dataSet) {
        if (querySet == dataSet) {
            return true;
        }
        // SET_ALL matches all non-debugging sets.
        return querySet == SET_ALL && dataSet < SET_DEBUG_START;
    }

    /**
     * Return text description of {@link #tag} value.
     */
@@ -843,6 +869,9 @@ public class NetworkStats implements Parcelable {
            if (recycle.uid == UID_ALL) {
                throw new IllegalStateException(
                        "Cannot adjust VPN accounting on an iface aggregated NetworkStats.");
            } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
                throw new IllegalStateException(
                        "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*");
            }

            if (recycle.uid == tunUid && recycle.tag == TAG_NONE
@@ -906,6 +935,9 @@ public class NetworkStats implements Parcelable {
                combineValues(tmpEntry);
                if (tag[i] == TAG_NONE) {
                    moved.add(tmpEntry);
                    // Add debug info
                    tmpEntry.set = SET_DBG_VPN_IN;
                    combineValues(tmpEntry);
                }
            }
        }
@@ -913,6 +945,13 @@ public class NetworkStats implements Parcelable {
    }

    private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) {
        // Add debug info
        moved.uid = tunUid;
        moved.set = SET_DBG_VPN_OUT;
        moved.tag = TAG_NONE;
        moved.iface = underlyingIface;
        combineValues(moved);

        // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
        // the TAG_NONE traffic.
        int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE);
+26 −5
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package android.net;

import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.SET_DBG_VPN_IN;
import static android.net.NetworkStats.SET_DBG_VPN_OUT;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.TAG_NONE;
@@ -346,7 +348,7 @@ public class NetworkStatsTest extends TestCase {
            .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L);

        assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface));
        assertEquals(17, delta.size());
        assertEquals(21, delta.size());

        // tunIface and TEST_IFACE entries are not changed.
        assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE,
@@ -377,14 +379,33 @@ public class NetworkStatsTest extends TestCase {
                0L, 0L, 0L, 0L, 0L);

        // New entries are added for new application's underlying Iface traffic
        assertValues(delta, 13, underlyingIface, 10120, SET_DEFAULT, TAG_NONE,
        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE,
                72667L, 197L, 41872l, 219L, 0L);
        assertValues(delta, 14, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE,
        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE,
                9297L, 17L, 3936, 19L, 0L);
        assertValues(delta, 15, underlyingIface, 10120, SET_DEFAULT, testTag1,
        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1,
                21691L, 41L, 13179L, 46L, 0L);
        assertValues(delta, 16, underlyingIface, 10120, SET_FOREGROUND, testTag1,
        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1,
                1281L, 2L, 634L, 1L, 0L);

        // New entries are added for debug purpose
        assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE,
                39605L, 46L, 11690, 49, 0);
        assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE,
                81964, 214, 45808, 238, 0);
        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE,
                4983, 10, 1717, 10, 0);
        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE,
                126552, 270, 59215, 297, 0);

    }

    private static void assertContains(NetworkStats stats,  String iface, int uid, int set,
            int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
        int index = stats.findIndex(iface, uid, set, tag);
        assertTrue(index != -1);
        assertValues(stats, index, iface, uid, set, tag,
                rxBytes, rxPackets, txBytes, txPackets, operations);
    }

    private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
+4 −3
Original line number Diff line number Diff line
@@ -182,8 +182,7 @@ public class NetworkStatsCollection implements FileRotator.Reader {

        for (int i = 0; i < mStats.size(); i++) {
            final Key key = mStats.keyAt(i);
            final boolean setMatches = set == SET_ALL || key.set == set;
            if (key.uid == uid && setMatches && key.tag == tag
            if (key.uid == uid && NetworkStats.setMatches(set, key.set) && key.tag == tag
                    && templateMatches(template, key.ident)) {
                final NetworkStatsHistory value = mStats.valueAt(i);
                combined.recordHistory(value, start, end);
@@ -209,7 +208,8 @@ public class NetworkStatsCollection implements FileRotator.Reader {
        final int callerUid = Binder.getCallingUid();
        for (int i = 0; i < mStats.size(); i++) {
            final Key key = mStats.keyAt(i);
            if (templateMatches(template, key.ident) && isAccessibleToUser(key.uid, callerUid)) {
            if (templateMatches(template, key.ident) && isAccessibleToUser(key.uid, callerUid)
                    && key.set < NetworkStats.SET_DEBUG_START) {
                final NetworkStatsHistory value = mStats.valueAt(i);
                historyEntry = value.getValues(start, end, now, historyEntry);

@@ -542,6 +542,7 @@ public class NetworkStatsCollection implements FileRotator.Reader {
            final NetworkStatsHistory value = mStats.valueAt(i);

            if (!templateMatches(groupTemplate, key.ident)) continue;
            if (key.set >= NetworkStats.SET_DEBUG_START) continue;

            final Key groupKey = new Key(null, key.uid, key.set, key.tag);
            NetworkStatsHistory groupHistory = grouped.get(groupKey);