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

Commit 1b5a2a96 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Read "qtaguid" network stats, refactor templates.

Teach NMS to read qtaguid stats from kernel, but fall back to older
stats when kernel doesn't support.  Add "tags" to NetworkStats entries
to support qtaguid.  To work around double-reporting bug, subtract
tagged stats from TAG_NONE entry.

Flesh out stronger NetworkTemplate.  All NetworkStatsService requests
now require a template, and moved matching logic into template.

Record UID stats keyed on complete NetworkIdentitySet definition,
similar to how interface stats are stored.  Since previous UID stats
didn't have iface breakdown, discard during file format upgrade.

Change-Id: I0447b5e7d205d73d28e71c889c568e536e91b8e4
parent 1a81a16a
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -18,18 +18,19 @@ package android.net;

import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;

/** {@hide} */
interface INetworkStatsService {

    /** Return historical stats for traffic that matches template. */
    NetworkStatsHistory getHistoryForNetwork(int networkTemplate);
    NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template);
    /** Return historical stats for specific UID traffic that matches template. */
    NetworkStatsHistory getHistoryForUid(int uid, int networkTemplate);
    NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid);

    /** Return usage summary for traffic that matches template. */
    NetworkStats getSummaryForNetwork(long start, long end, int networkTemplate, String subscriberId);
    NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
    /** Return usage summary per UID for traffic that matches template. */
    NetworkStats getSummaryForAllUid(long start, long end, int networkTemplate);
    NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end);

}
+107 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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 android.net;

import static android.net.ConnectivityManager.isNetworkTypeMobile;

import android.content.Context;
import android.telephony.TelephonyManager;

import com.android.internal.util.Objects;

/**
 * Network definition that includes strong identity. Analogous to combining
 * {@link NetworkInfo} and an IMSI.
 *
 * @hide
 */
public class NetworkIdentity {
    final int mType;
    final int mSubType;
    final String mSubscriberId;

    public NetworkIdentity(int type, int subType, String subscriberId) {
        this.mType = type;
        this.mSubType = subType;
        this.mSubscriberId = subscriberId;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(mType, mSubType, mSubscriberId);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof NetworkIdentity) {
            final NetworkIdentity ident = (NetworkIdentity) obj;
            return mType == ident.mType && mSubType == ident.mSubType
                    && Objects.equal(mSubscriberId, ident.mSubscriberId);
        }
        return false;
    }

    @Override
    public String toString() {
        final String typeName = ConnectivityManager.getNetworkTypeName(mType);
        final String subTypeName;
        if (ConnectivityManager.isNetworkTypeMobile(mType)) {
            subTypeName = TelephonyManager.getNetworkTypeName(mSubType);
        } else {
            subTypeName = Integer.toString(mSubType);
        }

        final String scrubSubscriberId = mSubscriberId != null ? "valid" : "null";
        return "[type=" + typeName + ", subType=" + subTypeName + ", subscriberId="
                + scrubSubscriberId + "]";
    }

    public int getType() {
        return mType;
    }

    public int getSubType() {
        return mSubType;
    }

    public String getSubscriberId() {
        return mSubscriberId;
    }

    /**
     * Build a {@link NetworkIdentity} from the given {@link NetworkState},
     * assuming that any mobile networks are using the current IMSI.
     */
    public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
        final int type = state.networkInfo.getType();
        final int subType = state.networkInfo.getSubtype();

        // TODO: consider moving subscriberId over to LinkCapabilities, so it
        // comes from an authoritative source.

        final String subscriberId;
        if (isNetworkTypeMobile(type)) {
            final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
                    Context.TELEPHONY_SERVICE);
            subscriberId = telephony.getSubscriberId();
        } else {
            subscriberId = null;
        }
        return new NetworkIdentity(type, subType, subscriberId);
    }

}
+16 −16
Original line number Diff line number Diff line
@@ -16,37 +16,38 @@

package android.net;

import static com.android.internal.util.Preconditions.checkNotNull;

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

/**
 * Policy for a specific network, including usage cycle and limits to be
 * enforced.
 * Policy for networks matching a {@link NetworkTemplate}, including usage cycle
 * and limits to be enforced.
 *
 * @hide
 */
public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
    public final int networkTemplate;
    public final String subscriberId;
    public static final long WARNING_DISABLED = -1;
    public static final long LIMIT_DISABLED = -1;

    public final NetworkTemplate template;
    public int cycleDay;
    public long warningBytes;
    public long limitBytes;

    public static final long WARNING_DISABLED = -1;
    public static final long LIMIT_DISABLED = -1;
    // TODO: teach how to snooze limit for current cycle

    public NetworkPolicy(int networkTemplate, String subscriberId, int cycleDay, long warningBytes,
            long limitBytes) {
        this.networkTemplate = networkTemplate;
        this.subscriberId = subscriberId;
    public NetworkPolicy(
            NetworkTemplate template, int cycleDay, long warningBytes, long limitBytes) {
        this.template = checkNotNull(template, "missing NetworkTemplate");
        this.cycleDay = cycleDay;
        this.warningBytes = warningBytes;
        this.limitBytes = limitBytes;
    }

    public NetworkPolicy(Parcel in) {
        networkTemplate = in.readInt();
        subscriberId = in.readString();
        template = in.readParcelable(null);
        cycleDay = in.readInt();
        warningBytes = in.readLong();
        limitBytes = in.readLong();
@@ -54,8 +55,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {

    /** {@inheritDoc} */
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(networkTemplate);
        dest.writeString(subscriberId);
        dest.writeParcelable(template, flags);
        dest.writeInt(cycleDay);
        dest.writeLong(warningBytes);
        dest.writeLong(limitBytes);
@@ -81,8 +81,8 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {

    @Override
    public String toString() {
        return "NetworkPolicy: networkTemplate=" + networkTemplate + ", cycleDay=" + cycleDay
                + ", warningBytes=" + warningBytes + ", limitBytes=" + limitBytes;
        return "NetworkPolicy[" + template + "]: cycleDay=" + cycleDay + ", warningBytes="
                + warningBytes + ", limitBytes=" + limitBytes;
    }

    public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() {
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ public class NetworkPolicyManager {
    /**
     * {@link Intent} extra included in {@link #ACTION_DATA_USAGE_WARNING} and
     * {@link #ACTION_DATA_USAGE_LIMIT} to indicate which
     * {@link NetworkPolicy#networkTemplate} it applies to.
     * {@link NetworkTemplate} rule it applies to.
     */
    public static final String EXTRA_NETWORK_TEMPLATE =
            "android.intent.extra.NETWORK_TEMPLATE";
+34 −14
Original line number Diff line number Diff line
@@ -40,9 +40,8 @@ public class NetworkStats implements Parcelable {
    public static final String IFACE_ALL = null;
    /** {@link #uid} value when UID details unavailable. */
    public static final int UID_ALL = -1;

    // NOTE: data should only be accounted for once in this structure; if data
    // is broken out, the summarized version should not be included.
    /** {@link #tag} value for without tag. */
    public static final int TAG_NONE = 0;

    /**
     * {@link SystemClock#elapsedRealtime()} timestamp when this data was
@@ -52,16 +51,16 @@ public class NetworkStats implements Parcelable {
    public int size;
    public String[] iface;
    public int[] uid;
    public int[] tag;
    public long[] rx;
    public long[] tx;

    // TODO: add fg/bg stats once reported by kernel

    public NetworkStats(long elapsedRealtime, int initialSize) {
        this.elapsedRealtime = elapsedRealtime;
        this.size = 0;
        this.iface = new String[initialSize];
        this.uid = new int[initialSize];
        this.tag = new int[initialSize];
        this.rx = new long[initialSize];
        this.tx = new long[initialSize];
    }
@@ -71,21 +70,27 @@ public class NetworkStats implements Parcelable {
        size = parcel.readInt();
        iface = parcel.createStringArray();
        uid = parcel.createIntArray();
        tag = parcel.createIntArray();
        rx = parcel.createLongArray();
        tx = parcel.createLongArray();
    }

    public NetworkStats addEntry(String iface, int uid, long rx, long tx) {
    /**
     * Add new stats entry with given values.
     */
    public NetworkStats addEntry(String iface, int uid, int tag, long rx, long tx) {
        if (size >= this.iface.length) {
            final int newLength = Math.max(this.iface.length, 10) * 3 / 2;
            this.iface = Arrays.copyOf(this.iface, newLength);
            this.uid = Arrays.copyOf(this.uid, newLength);
            this.tag = Arrays.copyOf(this.tag, newLength);
            this.rx = Arrays.copyOf(this.rx, newLength);
            this.tx = Arrays.copyOf(this.tx, newLength);
        }

        this.iface[size] = iface;
        this.uid[size] = uid;
        this.tag[size] = tag;
        this.rx[size] = rx;
        this.tx[size] = tx;
        size++;
@@ -93,17 +98,29 @@ public class NetworkStats implements Parcelable {
        return this;
    }

    @Deprecated
    public int length() {
        return size;
    /**
     * Combine given values with an existing row, or create a new row if
     * {@link #findIndex(String, int, int)} is unable to find match. Can also be
     * used to subtract values from existing rows.
     */
    public NetworkStats combineEntry(String iface, int uid, int tag, long rx, long tx) {
        final int i = findIndex(iface, uid, tag);
        if (i == -1) {
            // only create new entry when positive contribution
            addEntry(iface, uid, tag, rx, tx);
        } else {
            this.rx[i] += rx;
            this.tx[i] += tx;
        }
        return this;
    }

    /**
     * Find first stats index that matches the requested parameters.
     */
    public int findIndex(String iface, int uid) {
    public int findIndex(String iface, int uid, int tag) {
        for (int i = 0; i < size; i++) {
            if (equal(iface, this.iface[i]) && uid == this.uid[i]) {
            if (equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) {
                return i;
            }
        }
@@ -186,12 +203,13 @@ public class NetworkStats implements Parcelable {
        for (int i = 0; i < size; i++) {
            final String iface = this.iface[i];
            final int uid = this.uid[i];
            final int tag = this.tag[i];

            // find remote row that matches, and subtract
            final int j = value.findIndex(iface, uid);
            final int j = value.findIndex(iface, uid, tag);
            if (j == -1) {
                // newly appearing row, return entire value
                result.addEntry(iface, uid, this.rx[i], this.tx[i]);
                result.addEntry(iface, uid, tag, this.rx[i], this.tx[i]);
            } else {
                // existing row, subtract remote value
                long rx = this.rx[i] - value.rx[j];
@@ -203,7 +221,7 @@ public class NetworkStats implements Parcelable {
                    rx = Math.max(0, rx);
                    tx = Math.max(0, tx);
                }
                result.addEntry(iface, uid, rx, tx);
                result.addEntry(iface, uid, tag, rx, tx);
            }
        }

@@ -221,6 +239,7 @@ public class NetworkStats implements Parcelable {
            pw.print(prefix);
            pw.print("  iface="); pw.print(iface[i]);
            pw.print(" uid="); pw.print(uid[i]);
            pw.print(" tag="); pw.print(tag[i]);
            pw.print(" rx="); pw.print(rx[i]);
            pw.print(" tx="); pw.println(tx[i]);
        }
@@ -244,6 +263,7 @@ public class NetworkStats implements Parcelable {
        dest.writeInt(size);
        dest.writeStringArray(iface);
        dest.writeIntArray(uid);
        dest.writeIntArray(tag);
        dest.writeLongArray(rx);
        dest.writeLongArray(tx);
    }
Loading