diff options
| author | 2013-02-05 21:32:33 -0800 | |
|---|---|---|
| committer | 2013-02-06 16:23:12 -0800 | |
| commit | 4b17a1321db24b1a59c29b580aed7482a43febee (patch) | |
| tree | 07edf9ff9d9f96624f1aebd893cd757462e5f5eb | |
| parent | cd80392fe706e0b419a3e655702006a25d397243 (diff) | |
Offer parsed TCP interface statistics.
Also switch to newer iface_stat_fmt numbers, which are measured at
XT level instead of dev.
Bug: 7903145, 6569689
Change-Id: Ibeb742966b8c89916ea31a49388a5dbe25a5f67f
| -rw-r--r-- | core/java/android/net/TrafficStats.java | 26 | ||||
| -rw-r--r-- | core/jni/android_net_TrafficStats.cpp | 137 |
2 files changed, 103 insertions, 60 deletions
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e437d2e3475b..a014cec3fe91 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -315,6 +315,30 @@ public class TrafficStats { return total; } + /** {@hide} */ + public static long getMobileTcpRxPackets() { + long total = 0; + for (String iface : getMobileIfaces()) { + final long stat = nativeGetIfaceStat(iface, TYPE_TCP_RX_PACKETS); + if (stat != UNSUPPORTED) { + total += stat; + } + } + return total; + } + + /** {@hide} */ + public static long getMobileTcpTxPackets() { + long total = 0; + for (String iface : getMobileIfaces()) { + final long stat = nativeGetIfaceStat(iface, TYPE_TCP_TX_PACKETS); + if (stat != UNSUPPORTED) { + total += stat; + } + } + return total; + } + /** * Get the total number of packets transmitted through the specified interface. * @@ -587,6 +611,8 @@ public class TrafficStats { 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 final int TYPE_TCP_RX_PACKETS = 4; + private static final int TYPE_TCP_TX_PACKETS = 5; private static native long nativeGetTotalStat(int type); private static native long nativeGetIfaceStat(String iface, int type); diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp index 325fe2604117..aa8a58b48330 100644 --- a/core/jni/android_net_TrafficStats.cpp +++ b/core/jni/android_net_TrafficStats.cpp @@ -31,8 +31,7 @@ namespace android { -static const uint64_t VALUE_UNKNOWN = -1; -static const char* IFACE_STAT_ALL = "/proc/net/xt_qtaguid/iface_stat_all"; +static const char* QTAGUID_IFACE_STATS = "/proc/net/xt_qtaguid/iface_stat_fmt"; enum Tx_Rx { TX, @@ -46,20 +45,45 @@ enum Tcp_Udp { }; // NOTE: keep these in sync with TrafficStats.java -enum IfaceStatType { +static const uint64_t UNKNOWN = -1; + +enum StatsType { RX_BYTES = 0, RX_PACKETS = 1, TX_BYTES = 2, - TX_PACKETS = 3 + TX_PACKETS = 3, + TCP_RX_PACKETS = 4, + TCP_TX_PACKETS = 5 }; -struct IfaceStat { +struct Stats { uint64_t rxBytes; uint64_t rxPackets; uint64_t txBytes; uint64_t txPackets; + uint64_t tcpRxPackets; + uint64_t tcpTxPackets; }; +static uint64_t getStatsType(struct Stats* stats, StatsType type) { + switch (type) { + case RX_BYTES: + return stats->rxBytes; + case RX_PACKETS: + return stats->rxPackets; + case TX_BYTES: + return stats->txBytes; + case TX_PACKETS: + return stats->txPackets; + case TCP_RX_PACKETS: + return stats->tcpRxPackets; + case TCP_TX_PACKETS: + return stats->tcpTxPackets; + default: + return UNKNOWN; + } +} + // Returns an ASCII decimal number read from the specified file, -1 on error. static jlong readNumber(char const* filename) { char buf[80]; @@ -81,79 +105,72 @@ static jlong readNumber(char const* filename) { return atoll(buf); } -static int parseIfaceStat(const char* iface, struct IfaceStat* stat) { - FILE *fp = fopen(IFACE_STAT_ALL, "r"); - if (!fp) { - return errno; +static int parseIfaceStats(const char* iface, struct Stats* stats) { + FILE *fp = fopen(QTAGUID_IFACE_STATS, "r"); + if (fp == NULL) { + return -1; } char buffer[256]; char cur_iface[32]; - int active; - uint64_t rxBytes, rxPackets, txBytes, txPackets, devRxBytes, devRxPackets, devTxBytes, - devTxPackets; - - 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; - } - - if (!iface || !strcmp(iface, cur_iface)) { - stat->rxBytes += rxBytes; - stat->rxPackets += rxPackets; - stat->txBytes += txBytes; - stat->txPackets += txPackets; - - if (active) { - stat->rxBytes += devRxBytes; - stat->rxPackets += devRxPackets; - stat->txBytes += devTxBytes; - stat->txPackets += devTxPackets; + bool foundTcp = false; + uint64_t rxBytes, rxPackets, txBytes, txPackets, tcpRxPackets, tcpTxPackets; + + while (fgets(buffer, sizeof(buffer), fp) != NULL) { + int matched = sscanf(buffer, "%31s %llu %llu %llu %llu " + "%*llu %llu %*llu %*llu %*llu %*llu " + "%*llu %llu %*llu %*llu %*llu %*llu", cur_iface, &rxBytes, + &rxPackets, &txBytes, &txPackets, &tcpRxPackets, &tcpTxPackets); + if (matched >= 5) { + if (matched == 7) { + foundTcp = true; + } + if (!iface || !strcmp(iface, cur_iface)) { + stats->rxBytes += rxBytes; + stats->rxPackets += rxPackets; + stats->txBytes += txBytes; + stats->txPackets += txPackets; + if (matched == 7) { + stats->tcpRxPackets += tcpRxPackets; + stats->tcpTxPackets += tcpTxPackets; + } } } } - fclose(fp); - return 0; -} - -static uint64_t getIfaceStatType(const char* iface, IfaceStatType type) { - struct IfaceStat stat; - memset(&stat, 0, sizeof(IfaceStat)); - - if (parseIfaceStat(iface, &stat)) { - return VALUE_UNKNOWN; + if (!foundTcp) { + stats->tcpRxPackets = UNKNOWN; + stats->tcpTxPackets = UNKNOWN; } - 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; + if (fclose(fp) != 0) { + return -1; } + return 0; } static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) { - return getIfaceStatType(NULL, (IfaceStatType) type); + struct Stats stats; + memset(&stats, 0, sizeof(Stats)); + if (parseIfaceStats(NULL, &stats) == 0) { + return getStatsType(&stats, (StatsType) type); + } else { + return UNKNOWN; + } } 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; + ScopedUtfChars iface8(env, iface); + if (iface8.c_str() == NULL) { + return UNKNOWN; + } + + struct Stats stats; + memset(&stats, 0, sizeof(Stats)); + if (parseIfaceStats(NULL, &stats) == 0) { + return getStatsType(&stats, (StatsType) type); } else { - return VALUE_UNKNOWN; + return UNKNOWN; } } |