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

Commit 55a442e5 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Lightweight checkin output for network stats.

Define and print a compact version of network statistics when dump
is requested with the "--checkin" flag.  Defaults to last 24 hours,
but included data can be tweaked with various flags.

Groups together detailed network identities into larger umbrella
terms like "mobile" and "wifi."

Bug: 18415963
Change-Id: I70cf9c828ea5c6e5bb6884837d3608f66fbad2e6
parent 26750711
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ import java.util.Objects;
 *
 * @hide
 */
public class NetworkIdentity {
public class NetworkIdentity implements Comparable<NetworkIdentity> {
    /**
     * When enabled, combine all {@link #mSubType} together under
     * {@link #SUBTYPE_COMBINED}.
@@ -76,7 +76,7 @@ public class NetworkIdentity {

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder("[");
        final StringBuilder builder = new StringBuilder("{");
        builder.append("type=").append(getNetworkTypeName(mType));
        builder.append(", subType=");
        if (COMBINE_SUBTYPE_ENABLED) {
@@ -95,7 +95,7 @@ public class NetworkIdentity {
        if (mRoaming) {
            builder.append(", ROAMING");
        }
        return builder.append("]").toString();
        return builder.append("}").toString();
    }

    public int getType() {
@@ -170,4 +170,22 @@ public class NetworkIdentity {

        return new NetworkIdentity(type, subType, subscriberId, networkId, roaming);
    }

    @Override
    public int compareTo(NetworkIdentity another) {
        int res = Integer.compare(mType, another.mType);
        if (res == 0) {
            res = Integer.compare(mSubType, another.mSubType);
        }
        if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) {
            res = mSubscriberId.compareTo(another.mSubscriberId);
        }
        if (res == 0 && mNetworkId != null && another.mNetworkId != null) {
            res = mNetworkId.compareTo(another.mNetworkId);
        }
        if (res == 0) {
            res = Boolean.compare(mRoaming, another.mRoaming);
        }
        return res;
    }
}
+16 −0
Original line number Diff line number Diff line
@@ -732,6 +732,22 @@ public class NetworkStats implements Parcelable {
        }
    }

    /**
     * Return text description of {@link #set} value.
     */
    public static String setToCheckinString(int set) {
        switch (set) {
            case SET_ALL:
                return "all";
            case SET_DEFAULT:
                return "def";
            case SET_FOREGROUND:
                return "fg";
            default:
                return "unk";
        }
    }

    /**
     * Return text description of {@link #tag} value.
     */
+40 −8
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray;
import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray;
import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.internal.util.ArrayUtils.total;

import android.os.Parcel;
@@ -38,6 +39,7 @@ import java.io.CharArrayWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ProtocolException;
import java.util.Arrays;
import java.util.Random;
@@ -573,8 +575,22 @@ public class NetworkStatsHistory implements Parcelable {
        return (long) (start + (r.nextFloat() * (end - start)));
    }

    /**
     * Quickly determine if this history intersects with given window.
     */
    public boolean intersects(long start, long end) {
        final long dataStart = getStart();
        final long dataEnd = getEnd();
        if (start >= dataStart && start <= dataEnd) return true;
        if (end >= dataStart && end <= dataEnd) return true;
        if (dataStart >= start && dataStart <= end) return true;
        if (dataEnd >= start && dataEnd <= end) return true;
        return false;
    }

    public void dump(IndentingPrintWriter pw, boolean fullHistory) {
        pw.print("NetworkStatsHistory: bucketDuration="); pw.println(bucketDuration);
        pw.print("NetworkStatsHistory: bucketDuration=");
        pw.println(bucketDuration / SECOND_IN_MILLIS);
        pw.increaseIndent();

        final int start = fullHistory ? 0 : Math.max(0, bucketCount - 32);
@@ -583,19 +599,35 @@ public class NetworkStatsHistory implements Parcelable {
        }

        for (int i = start; i < bucketCount; i++) {
            pw.print("bucketStart="); pw.print(bucketStart[i]);
            if (activeTime != null) { pw.print(" activeTime="); pw.print(activeTime[i]); }
            if (rxBytes != null) { pw.print(" rxBytes="); pw.print(rxBytes[i]); }
            if (rxPackets != null) { pw.print(" rxPackets="); pw.print(rxPackets[i]); }
            if (txBytes != null) { pw.print(" txBytes="); pw.print(txBytes[i]); }
            if (txPackets != null) { pw.print(" txPackets="); pw.print(txPackets[i]); }
            if (operations != null) { pw.print(" operations="); pw.print(operations[i]); }
            pw.print("st="); pw.print(bucketStart[i] / SECOND_IN_MILLIS);
            if (rxBytes != null) { pw.print(" rb="); pw.print(rxBytes[i]); }
            if (rxPackets != null) { pw.print(" rp="); pw.print(rxPackets[i]); }
            if (txBytes != null) { pw.print(" tb="); pw.print(txBytes[i]); }
            if (txPackets != null) { pw.print(" tp="); pw.print(txPackets[i]); }
            if (operations != null) { pw.print(" op="); pw.print(operations[i]); }
            pw.println();
        }

        pw.decreaseIndent();
    }

    public void dumpCheckin(PrintWriter pw) {
        pw.print("d,");
        pw.print(bucketDuration / SECOND_IN_MILLIS);
        pw.println();

        for (int i = 0; i < bucketCount; i++) {
            pw.print("b,");
            pw.print(bucketStart[i] / SECOND_IN_MILLIS); pw.print(',');
            if (rxBytes != null) { pw.print(rxBytes[i]); } else { pw.print("*"); } pw.print(',');
            if (rxPackets != null) { pw.print(rxPackets[i]); } else { pw.print("*"); } pw.print(',');
            if (txBytes != null) { pw.print(txBytes[i]); } else { pw.print("*"); } pw.print(',');
            if (txPackets != null) { pw.print(txPackets[i]); } else { pw.print("*"); } pw.print(',');
            if (operations != null) { pw.print(operations[i]); } else { pw.print("*"); }
            pw.println();
        }
    }

    @Override
    public String toString() {
        final CharArrayWriter writer = new CharArrayWriter();
+26 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.net;

import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
@@ -34,10 +35,10 @@ import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

import com.android.internal.annotations.VisibleForTesting;

import java.util.Objects;

/**
 * Template definition used to generically match {@link NetworkIdentity},
 * usually when collecting statistics.
@@ -53,6 +54,7 @@ public class NetworkTemplate implements Parcelable {
    public static final int MATCH_ETHERNET = 5;
    public static final int MATCH_MOBILE_WILDCARD = 6;
    public static final int MATCH_WIFI_WILDCARD = 7;
    public static final int MATCH_BLUETOOTH = 8;

    /**
     * Set of {@link NetworkInfo#getType()} that reflect data usage.
@@ -134,6 +136,14 @@ public class NetworkTemplate implements Parcelable {
        return new NetworkTemplate(MATCH_ETHERNET, null, null);
    }

    /**
     * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style
     * networks together.
     */
    public static NetworkTemplate buildTemplateBluetooth() {
        return new NetworkTemplate(MATCH_BLUETOOTH, null, null);
    }

    private final int mMatchRule;
    private final String mSubscriberId;
    private final String mNetworkId;
@@ -222,6 +232,8 @@ public class NetworkTemplate implements Parcelable {
                return matchesMobileWildcard(ident);
            case MATCH_WIFI_WILDCARD:
                return matchesWifiWildcard(ident);
            case MATCH_BLUETOOTH:
                return matchesBluetooth(ident);
            default:
                throw new IllegalArgumentException("unknown network template");
        }
@@ -316,6 +328,16 @@ public class NetworkTemplate implements Parcelable {
        }
    }

    /**
     * Check if matches Bluetooth network template.
     */
    private boolean matchesBluetooth(NetworkIdentity ident) {
        if (ident.mType == TYPE_BLUETOOTH) {
            return true;
        }
        return false;
    }

    private static String getMatchRuleName(int matchRule) {
        switch (matchRule) {
            case MATCH_MOBILE_3G_LOWER:
@@ -332,6 +354,8 @@ public class NetworkTemplate implements Parcelable {
                return "MOBILE_WILDCARD";
            case MATCH_WIFI_WILDCARD:
                return "WIFI_WILDCARD";
            case MATCH_BLUETOOTH:
                return "BLUETOOTH";
            default:
                return "UNKNOWN";
        }
+34 −0
Original line number Diff line number Diff line
@@ -451,6 +451,40 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
        assertIndexBeforeAfter(stats, 4, 4, Long.MAX_VALUE);
    }

    public void testIntersects() throws Exception {
        final long BUCKET_SIZE = HOUR_IN_MILLIS;
        stats = new NetworkStatsHistory(BUCKET_SIZE);

        final long FIRST_START = TEST_START;
        final long FIRST_END = FIRST_START + (2 * HOUR_IN_MILLIS);
        final long SECOND_START = TEST_START + WEEK_IN_MILLIS;
        final long SECOND_END = SECOND_START + HOUR_IN_MILLIS;
        final long THIRD_START = TEST_START + (2 * WEEK_IN_MILLIS);
        final long THIRD_END = THIRD_START + (2 * HOUR_IN_MILLIS);

        stats.recordData(FIRST_START, FIRST_END,
                new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
        stats.recordData(SECOND_START, SECOND_END,
                new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
        stats.recordData(THIRD_START, THIRD_END,
                new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));

        assertFalse(stats.intersects(10, 20));
        assertFalse(stats.intersects(TEST_START + YEAR_IN_MILLIS, TEST_START + YEAR_IN_MILLIS + 1));
        assertFalse(stats.intersects(Long.MAX_VALUE, Long.MIN_VALUE));

        assertTrue(stats.intersects(Long.MIN_VALUE, Long.MAX_VALUE));
        assertTrue(stats.intersects(10, TEST_START + YEAR_IN_MILLIS));
        assertTrue(stats.intersects(TEST_START, TEST_START));
        assertTrue(stats.intersects(TEST_START + DAY_IN_MILLIS, TEST_START + DAY_IN_MILLIS + 1));
        assertTrue(stats.intersects(TEST_START + DAY_IN_MILLIS, Long.MAX_VALUE));
        assertTrue(stats.intersects(TEST_START + 1, Long.MAX_VALUE));

        assertFalse(stats.intersects(Long.MIN_VALUE, TEST_START - 1));
        assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START));
        assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START + 1));
    }

    private static void assertIndexBeforeAfter(
            NetworkStatsHistory stats, int before, int after, long time) {
        assertEquals("unexpected before", before, stats.getIndexBefore(time));
Loading