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

Commit 12332877 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Move TrafficStats iface counters to xt_qtaguid."

parents c0e5b8c7 234766a3
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@ interface INetworkStatsService {

    /** Return data layer snapshot of UID network usage. */
    NetworkStats getDataLayerSnapshotForUid(int uid);
    /** Return set of any ifaces associated with mobile networks since boot. */
    String[] getMobileIfaces();

    /** Increment data layer count of operations performed for UID and tag. */
    void incrementOperationCount(int uid, int tag, int operationCount);

+38 −8
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ public class NetworkTemplate implements Parcelable {
    public static final int MATCH_MOBILE_4G = 3;
    public static final int MATCH_WIFI = 4;
    public static final int MATCH_ETHERNET = 5;
    public static final int MATCH_MOBILE_WILDCARD = 6;
    public static final int MATCH_WIFI_WILDCARD = 7;

    /**
     * Set of {@link NetworkInfo#getType()} that reflect data usage.
@@ -85,12 +87,20 @@ public class NetworkTemplate implements Parcelable {
        return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId, null);
    }

    /**
     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
     * regardless of IMSI.
     */
    public static NetworkTemplate buildTemplateMobileWildcard() {
        return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
    }

    /**
     * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
     * regardless of SSID.
     */
    public static NetworkTemplate buildTemplateWifiWildcard() {
        return new NetworkTemplate(MATCH_WIFI, null, null);
        return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
    }

    @Deprecated
@@ -198,6 +208,10 @@ public class NetworkTemplate implements Parcelable {
                return matchesWifi(ident);
            case MATCH_ETHERNET:
                return matchesEthernet(ident);
            case MATCH_MOBILE_WILDCARD:
                return matchesMobileWildcard(ident);
            case MATCH_WIFI_WILDCARD:
                return matchesWifiWildcard(ident);
            default:
                throw new IllegalArgumentException("unknown network template");
        }
@@ -257,13 +271,7 @@ public class NetworkTemplate implements Parcelable {
    private boolean matchesWifi(NetworkIdentity ident) {
        switch (ident.mType) {
            case TYPE_WIFI:
                if (mNetworkId == null) {
                    return true;
                } else {
                return Objects.equal(mNetworkId, ident.mNetworkId);
                }
            case TYPE_WIFI_P2P:
                return mNetworkId == null;
            default:
                return false;
        }
@@ -279,6 +287,24 @@ public class NetworkTemplate implements Parcelable {
        return false;
    }

    private boolean matchesMobileWildcard(NetworkIdentity ident) {
        if (ident.mType == TYPE_WIMAX) {
            return true;
        } else {
            return contains(DATA_USAGE_NETWORK_TYPES, ident.mType);
        }
    }

    private boolean matchesWifiWildcard(NetworkIdentity ident) {
        switch (ident.mType) {
            case TYPE_WIFI:
            case TYPE_WIFI_P2P:
                return true;
            default:
                return false;
        }
    }

    private static String getMatchRuleName(int matchRule) {
        switch (matchRule) {
            case MATCH_MOBILE_3G_LOWER:
@@ -291,6 +317,10 @@ public class NetworkTemplate implements Parcelable {
                return "WIFI";
            case MATCH_ETHERNET:
                return "ETHERNET";
            case MATCH_MOBILE_WILDCARD:
                return "MOBILE_WILDCARD";
            case MATCH_WIFI_WILDCARD:
                return "WIFI_WILDCARD";
            default:
                return "UNKNOWN";
        }
+86 −20
Original line number Diff line number Diff line
@@ -88,6 +88,16 @@ public class TrafficStats {
     */
    public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;

    private static INetworkStatsService sStatsService;

    private synchronized static INetworkStatsService getStatsService() {
        if (sStatsService == null) {
            sStatsService = INetworkStatsService.Stub.asInterface(
                    ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
        }
        return sStatsService;
    }

    /**
     * Snapshot of {@link NetworkStats} when the currently active profiling
     * session started, or {@code null} if no session active.
@@ -228,11 +238,9 @@ public class TrafficStats {
     * @param operationCount Number of operations to increment count by.
     */
    public static void incrementOperationCount(int tag, int operationCount) {
        final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
        final int uid = android.os.Process.myUid();
        try {
            statsService.incrementOperationCount(uid, tag, operationCount);
            getStatsService().incrementOperationCount(uid, tag, operationCount);
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
@@ -257,7 +265,13 @@ public class TrafficStats {
     * @return number of packets.  If the statistics are not supported by this device,
     * {@link #UNSUPPORTED} will be returned.
     */
    public static native long getMobileTxPackets();
    public static long getMobileTxPackets() {
        long total = 0;
        for (String iface : getMobileIfaces()) {
            total += getTxPackets(iface);
        }
        return total;
    }

    /**
     * Get the total number of packets received through the mobile interface.
@@ -265,7 +279,13 @@ public class TrafficStats {
     * @return number of packets.  If the statistics are not supported by this device,
     * {@link #UNSUPPORTED} will be returned.
     */
    public static native long getMobileRxPackets();
    public static long getMobileRxPackets() {
        long total = 0;
        for (String iface : getMobileIfaces()) {
            total += getRxPackets(iface);
        }
        return total;
    }

    /**
     * Get the total number of bytes transmitted through the mobile interface.
@@ -273,7 +293,13 @@ public class TrafficStats {
     * @return number of bytes.  If the statistics are not supported by this device,
     * {@link #UNSUPPORTED} will be returned.
     */
      public static native long getMobileTxBytes();
    public static long getMobileTxBytes() {
        long total = 0;
        for (String iface : getMobileIfaces()) {
            total += getTxBytes(iface);
        }
        return total;
    }

    /**
     * Get the total number of bytes received through the mobile interface.
@@ -281,7 +307,13 @@ public class TrafficStats {
     * @return number of bytes.  If the statistics are not supported by this device,
     * {@link #UNSUPPORTED} will be returned.
     */
    public static native long getMobileRxBytes();
    public static long getMobileRxBytes() {
        long total = 0;
        for (String iface : getMobileIfaces()) {
            total += getRxBytes(iface);
        }
        return total;
    }

    /**
     * Get the total number of packets transmitted through the specified interface.
@@ -290,7 +322,9 @@ public class TrafficStats {
     * {@link #UNSUPPORTED} will be returned.
     * @hide
     */
    public static native long getTxPackets(String iface);
    public static long getTxPackets(String iface) {
        return nativeGetIfaceStat(iface, TYPE_TX_PACKETS);
    }

    /**
     * Get the total number of packets received through the specified interface.
@@ -299,7 +333,9 @@ public class TrafficStats {
     * {@link #UNSUPPORTED} will be returned.
     * @hide
     */
    public static native long getRxPackets(String iface);
    public static long getRxPackets(String iface) {
        return nativeGetIfaceStat(iface, TYPE_RX_PACKETS);
    }

    /**
     * Get the total number of bytes transmitted through the specified interface.
@@ -308,7 +344,9 @@ public class TrafficStats {
     * {@link #UNSUPPORTED} will be returned.
     * @hide
     */
    public static native long getTxBytes(String iface);
    public static long getTxBytes(String iface) {
        return nativeGetIfaceStat(iface, TYPE_TX_BYTES);
    }

    /**
     * Get the total number of bytes received through the specified interface.
@@ -317,8 +355,9 @@ public class TrafficStats {
     * {@link #UNSUPPORTED} will be returned.
     * @hide
     */
    public static native long getRxBytes(String iface);

    public static long getRxBytes(String iface) {
        return nativeGetIfaceStat(iface, TYPE_RX_BYTES);
    }

    /**
     * Get the total number of packets sent through all network interfaces.
@@ -326,7 +365,9 @@ public class TrafficStats {
     * @return the number of packets.  If the statistics are not supported by this device,
     * {@link #UNSUPPORTED} will be returned.
     */
    public static native long getTotalTxPackets();
    public static long getTotalTxPackets() {
        return nativeGetTotalStat(TYPE_TX_PACKETS);
    }

    /**
     * Get the total number of packets received through all network interfaces.
@@ -334,7 +375,9 @@ public class TrafficStats {
     * @return number of packets.  If the statistics are not supported by this device,
     * {@link #UNSUPPORTED} will be returned.
     */
    public static native long getTotalRxPackets();
    public static long getTotalRxPackets() {
        return nativeGetTotalStat(TYPE_RX_PACKETS);
    }

    /**
     * Get the total number of bytes sent through all network interfaces.
@@ -342,7 +385,9 @@ public class TrafficStats {
     * @return number of bytes.  If the statistics are not supported by this device,
     * {@link #UNSUPPORTED} will be returned.
     */
    public static native long getTotalTxBytes();
    public static long getTotalTxBytes() {
        return nativeGetTotalStat(TYPE_TX_BYTES);
    }

    /**
     * Get the total number of bytes received through all network interfaces.
@@ -350,7 +395,9 @@ public class TrafficStats {
     * @return number of bytes.  If the statistics are not supported by this device,
     * {@link #UNSUPPORTED} will be returned.
     */
    public static native long getTotalRxBytes();
    public static long getTotalRxBytes() {
        return nativeGetTotalStat(TYPE_RX_BYTES);
    }

    /**
     * Get the number of bytes sent through the network for this UID.
@@ -483,7 +530,6 @@ public class TrafficStats {
     */
    public static native long getUidTcpRxSegments(int uid);


    /**
     * Get the number of UDP packets sent for this UID.
     * Includes DNS requests.
@@ -515,13 +561,33 @@ public class TrafficStats {
     * special permission.
     */
    private static NetworkStats getDataLayerSnapshotForUid(Context context) {
        final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
        final int uid = android.os.Process.myUid();
        try {
            return statsService.getDataLayerSnapshotForUid(uid);
            return getStatsService().getDataLayerSnapshotForUid(uid);
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Return set of any ifaces associated with mobile networks since boot.
     * Interfaces are never removed from this list, so counters should always be
     * monotonic.
     */
    private static String[] getMobileIfaces() {
        try {
            return getStatsService().getMobileIfaces();
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
    }

    // NOTE: keep these in sync with android_net_TrafficStats.cpp
    private static final int TYPE_RX_BYTES = 0;
    private static final int TYPE_RX_PACKETS = 1;
    private static final int TYPE_TX_BYTES = 2;
    private static final int TYPE_TX_PACKETS = 3;

    private static native long nativeGetTotalStat(int type);
    private static native long nativeGetIfaceStat(String iface, int type);
}
+79 −119
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@

namespace android {

static const uint64_t VALUE_UNKNOWN = -1;
static const char* IFACE_STAT_ALL = "/proc/net/xt_qtaguid/iface_stat_all";

enum Tx_Rx {
    TX,
    RX
@@ -42,6 +45,21 @@ enum Tcp_Udp {
    TCP_AND_UDP
};

// NOTE: keep these in sync with TrafficStats.java
enum IfaceStatType {
    RX_BYTES = 0,
    RX_PACKETS = 1,
    TX_BYTES = 2,
    TX_PACKETS = 3
};

struct IfaceStat {
    uint64_t rxBytes;
    uint64_t rxPackets;
    uint64_t txBytes;
    uint64_t txPackets;
};

// Returns an ASCII decimal number read from the specified file, -1 on error.
static jlong readNumber(char const* filename) {
    char buf[80];
@@ -63,130 +81,82 @@ static jlong readNumber(char const* filename) {
    return atoll(buf);
}

static const char* mobile_iface_list[] = {
    "rmnet0",
    "rmnet1",
    "rmnet2",
    "rmnet3",
    "cdma_rmnet4",
    "ppp0",
    0
};

static jlong getAll(const char** iface_list, const char* what) {

    char filename[80];
    int idx = 0;
    bool supported = false;
    jlong total = 0;
    while (iface_list[idx] != 0) {

        snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s",
                 iface_list[idx], what);
        jlong number = readNumber(filename);
        if (number >= 0) {
            supported = true;
            total += number;
        }
        idx++;
    }
    if (supported) return total;

    return -1;
}

// Returns the sum of numbers from the specified path under /sys/class/net/*,
// -1 if no such file exists.
static jlong readTotal(char const* suffix) {
    char filename[PATH_MAX] = "/sys/class/net/";
    DIR *dir = opendir(filename);
    if (dir == NULL) {
        ALOGE("Can't list %s: %s", filename, strerror(errno));
        return -1;
    }

    int len = strlen(filename);
    jlong total = -1;
    while (struct dirent *entry = readdir(dir)) {
        // Skip ., .., and localhost interfaces.
        if (entry->d_name[0] != '.' && strncmp(entry->d_name, "lo", 2) != 0) {
            strlcpy(filename + len, entry->d_name, sizeof(filename) - len);
            strlcat(filename, suffix, sizeof(filename));
            jlong num = readNumber(filename);
            if (num >= 0) total = total < 0 ? num : total + num;
        }
    }

    closedir(dir);
    return total;
static int parseIfaceStat(const char* iface, struct IfaceStat* stat) {
    FILE *fp = fopen(IFACE_STAT_ALL, "r");
    if (!fp) {
        return errno;
    }

// Mobile stats get accessed a lot more often than total stats.
// Note the individual files can come and go at runtime, so we check
// each file every time (rather than caching which ones exist).
    char buffer[256];
    char cur_iface[32];
    int active;
    uint64_t rxBytes, rxPackets, txBytes, txPackets, devRxBytes, devRxPackets, devTxBytes,
            devTxPackets;

static jlong getMobileTxPackets(JNIEnv* env, jobject clazz) {
    return getAll(mobile_iface_list, "tx_packets");
    while (fgets(buffer, 256, fp) != NULL) {
        if (sscanf(buffer, "%31s %d %llu %llu %llu %llu %llu %llu %llu %llu", cur_iface, &active,
                   &rxBytes, &rxPackets, &txBytes, &txPackets, &devRxBytes, &devRxPackets,
                   &devTxBytes, &devTxPackets) != 10) {
            continue;
        }

static jlong getMobileRxPackets(JNIEnv* env, jobject clazz) {
    return getAll(mobile_iface_list, "rx_packets");
}
        if (!iface || !strcmp(iface, cur_iface)) {
            stat->rxBytes += rxBytes;
            stat->rxPackets += rxPackets;
            stat->txBytes += txBytes;
            stat->txPackets += txPackets;

static jlong getMobileTxBytes(JNIEnv* env, jobject clazz) {
    return getAll(mobile_iface_list, "tx_bytes");
            if (active) {
                stat->rxBytes += devRxBytes;
                stat->rxPackets += devRxPackets;
                stat->txBytes += devTxBytes;
                stat->txPackets += devTxPackets;
            }

static jlong getMobileRxBytes(JNIEnv* env, jobject clazz) {
    return getAll(mobile_iface_list, "rx_bytes");
        }

static jlong getData(JNIEnv* env, const char* what, jstring javaInterface) {
    ScopedUtfChars interface(env, javaInterface);
    if (interface.c_str() == NULL) {
        return -1;
    }

    char filename[80];
    snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s", interface.c_str(), what);
    return readNumber(filename);
    fclose(fp);
    return 0;
}

static jlong getTxPackets(JNIEnv* env, jobject clazz, jstring interface) {
    return getData(env, "tx_packets", interface);
}
static uint64_t getIfaceStatType(const char* iface, IfaceStatType type) {
    struct IfaceStat stat;
    memset(&stat, 0, sizeof(IfaceStat));

static jlong getRxPackets(JNIEnv* env, jobject clazz, jstring interface) {
    return getData(env, "rx_packets", interface);
    if (parseIfaceStat(iface, &stat)) {
        return VALUE_UNKNOWN;
    }

static jlong getTxBytes(JNIEnv* env, jobject clazz, jstring interface) {
    return getData(env, "tx_bytes", interface);
    switch (type) {
        case RX_BYTES:
            return stat.rxBytes;
        case RX_PACKETS:
            return stat.rxPackets;
        case TX_BYTES:
            return stat.txBytes;
        case TX_PACKETS:
            return stat.txPackets;
        default:
            return VALUE_UNKNOWN;
    }

static jlong getRxBytes(JNIEnv* env, jobject clazz, jstring interface) {
    return getData(env, "rx_bytes", interface);
}


// Total stats are read less often, so we're willing to put up
// with listing the directory and concatenating filenames.

static jlong getTotalTxPackets(JNIEnv* env, jobject clazz) {
    return readTotal("/statistics/tx_packets");
static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
    return getIfaceStatType(NULL, (IfaceStatType) type);
}

static jlong getTotalRxPackets(JNIEnv* env, jobject clazz) {
    return readTotal("/statistics/rx_packets");
static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
    struct IfaceStat stat;
    const char* ifaceChars = env->GetStringUTFChars(iface, NULL);
    if (ifaceChars) {
        uint64_t stat = getIfaceStatType(ifaceChars, (IfaceStatType) type);
        env->ReleaseStringUTFChars(iface, ifaceChars);
        return stat;
    } else {
        return VALUE_UNKNOWN;
    }

static jlong getTotalTxBytes(JNIEnv* env, jobject clazz) {
    return readTotal("/statistics/tx_bytes");
}

static jlong getTotalRxBytes(JNIEnv* env, jobject clazz) {
    return readTotal("/statistics/rx_bytes");
}

// Per-UID stats require reading from a constructed filename.

@@ -323,18 +293,8 @@ static jlong getUidUdpRxPackets(JNIEnv* env, jobject clazz, jint uid) {
}

static JNINativeMethod gMethods[] = {
    {"getMobileTxPackets", "()J", (void*) getMobileTxPackets},
    {"getMobileRxPackets", "()J", (void*) getMobileRxPackets},
    {"getMobileTxBytes", "()J", (void*) getMobileTxBytes},
    {"getMobileRxBytes", "()J", (void*) getMobileRxBytes},
    {"getTxPackets", "(Ljava/lang/String;)J", (void*) getTxPackets},
    {"getRxPackets", "(Ljava/lang/String;)J", (void*) getRxPackets},
    {"getTxBytes", "(Ljava/lang/String;)J", (void*) getTxBytes},
    {"getRxBytes", "(Ljava/lang/String;)J", (void*) getRxBytes},
    {"getTotalTxPackets", "()J", (void*) getTotalTxPackets},
    {"getTotalRxPackets", "()J", (void*) getTotalRxPackets},
    {"getTotalTxBytes", "()J", (void*) getTotalTxBytes},
    {"getTotalRxBytes", "()J", (void*) getTotalRxBytes},
    {"nativeGetTotalStat", "(I)J", (void*) getTotalStat},
    {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*) getIfaceStat},

    /* Per-UID Stats */
    {"getUidTxBytes", "(I)J", (void*) getUidTxBytes},
+19 −8
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.isNetworkTypeMobile;
import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_ALL;
@@ -33,7 +34,7 @@ import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
@@ -54,6 +55,8 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.internal.util.ArrayUtils.appendElement;
import static com.android.internal.util.ArrayUtils.contains;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
@@ -194,6 +197,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
    private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
    /** Current default active iface. */
    private String mActiveIface;
    /** Set of any ifaces associated with mobile networks since boot. */
    private String[] mMobileIfaces = new String[0];

    private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
            new DropBoxNonMonotonicObserver();
@@ -516,6 +521,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
        return dataLayer;
    }

    @Override
    public String[] getMobileIfaces() {
        return mMobileIfaces;
    }

    @Override
    public void incrementOperationCount(int uid, int tag, int operationCount) {
        if (Binder.getCallingUid() != uid) {
@@ -735,6 +745,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
                }

                ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));

                // remember any ifaces associated with mobile networks
                if (isNetworkTypeMobile(state.networkInfo.getType())) {
                    if (!contains(mMobileIfaces, iface)) {
                        mMobileIfaces = appendElement(String.class, mMobileIfaces, iface);
                    }
                }
            }
        }
    }
@@ -861,7 +878,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
        NetworkStats.Entry uidTotal;

        // collect mobile sample
        template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
        template = buildTemplateMobileWildcard();
        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
        xtTotal = new NetworkStats.Entry();
        uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
@@ -1022,12 +1039,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
        }
    };

    private static String getActiveSubscriberId(Context context) {
        final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
                Context.TELEPHONY_SERVICE);
        return telephony.getSubscriberId();
    }

    private boolean isBandwidthControlEnabled() {
        try {
            return mNetworkManager.isBandwidthControlEnabled();