android_net_TrafficStats.cpp revision f17b971a75577a3a0e5ab574618e0756d167f5d4
12b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor/* 22b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * Copyright (C) 2010 The Android Open Source Project 32b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * 42b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * Licensed under the Apache License, Version 2.0 (the "License"); 52b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * you may not use this file except in compliance with the License. 62b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * You may obtain a copy of the License at 72b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * 82b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * http://www.apache.org/licenses/LICENSE-2.0 92b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * 102b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * Unless required by applicable law or agreed to in writing, software 112b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * distributed under the License is distributed on an "AS IS" BASIS, 122b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * See the License for the specific language governing permissions and 142b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor * limitations under the License. 152b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor */ 162b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 172b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#define LOG_TAG "TrafficStats" 182b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 192b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <dirent.h> 202b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <errno.h> 212b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <fcntl.h> 222b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <sys/stat.h> 232b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <sys/types.h> 242b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 252b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <android_runtime/AndroidRuntime.h> 262b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <cutils/logger.h> 272b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <jni.h> 28f17b971a75577a3a0e5ab574618e0756d167f5d4Elliott Hughes#include <ScopedUtfChars.h> 292b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <utils/misc.h> 302b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor#include <utils/Log.h> 312b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 322b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnornamespace android { 332b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 34c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmaenum Tx_Rx { 35c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma TX, 36c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma RX 37c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma}; 38c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 39c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmaenum Tcp_Udp { 40c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma TCP, 41c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma UDP, 42c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma TCP_AND_UDP 43c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma}; 44c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 452b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// Returns an ASCII decimal number read from the specified file, -1 on error. 462b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong readNumber(char const* filename) { 474e8d8238e10d168b434dcdd2e779a9aab37f1e2cDan Egnor#ifdef HAVE_ANDROID_OS 482b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor char buf[80]; 492b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor int fd = open(filename, O_RDONLY); 502b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor if (fd < 0) { 512b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor if (errno != ENOENT) LOGE("Can't open %s: %s", filename, strerror(errno)); 522b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return -1; 532b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor } 542b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 552b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor int len = read(fd, buf, sizeof(buf) - 1); 562b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor if (len < 0) { 572b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor LOGE("Can't read %s: %s", filename, strerror(errno)); 582b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor close(fd); 592b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return -1; 602b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor } 612b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 622b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor close(fd); 632b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor buf[len] = '\0'; 642b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return atoll(buf); 654e8d8238e10d168b434dcdd2e779a9aab37f1e2cDan Egnor#else // Simulator 664e8d8238e10d168b434dcdd2e779a9aab37f1e2cDan Egnor return -1; 674e8d8238e10d168b434dcdd2e779a9aab37f1e2cDan Egnor#endif 682b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 692b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 702b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// Return the number from the first file which exists and contains data 712b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong tryBoth(char const* a, char const* b) { 722b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor jlong num = readNumber(a); 732b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return num >= 0 ? num : readNumber(b); 742b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 752b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 762b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// Returns the sum of numbers from the specified path under /sys/class/net/*, 772b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// -1 if no such file exists. 782b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong readTotal(char const* suffix) { 794e8d8238e10d168b434dcdd2e779a9aab37f1e2cDan Egnor#ifdef HAVE_ANDROID_OS 802b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor char filename[PATH_MAX] = "/sys/class/net/"; 812b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor DIR *dir = opendir(filename); 822b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor if (dir == NULL) { 832b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor LOGE("Can't list %s: %s", filename, strerror(errno)); 842b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return -1; 852b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor } 862b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 872b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor int len = strlen(filename); 882b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor jlong total = -1; 892b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor while (struct dirent *entry = readdir(dir)) { 902b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor // Skip ., .., and localhost interfaces. 912b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor if (entry->d_name[0] != '.' && strncmp(entry->d_name, "lo", 2) != 0) { 922b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor strlcpy(filename + len, entry->d_name, sizeof(filename) - len); 932b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor strlcat(filename, suffix, sizeof(filename)); 942b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor jlong num = readNumber(filename); 952b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor if (num >= 0) total = total < 0 ? num : total + num; 962b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor } 972b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor } 982b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 992b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor closedir(dir); 1002b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return total; 1014e8d8238e10d168b434dcdd2e779a9aab37f1e2cDan Egnor#else // Simulator 1024e8d8238e10d168b434dcdd2e779a9aab37f1e2cDan Egnor return -1; 1034e8d8238e10d168b434dcdd2e779a9aab37f1e2cDan Egnor#endif 1042b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 1052b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1062b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// Mobile stats get accessed a lot more often than total stats. 1072b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// Note the individual files can come and go at runtime, so we check 1082b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// each file every time (rather than caching which ones exist). 1092b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1102b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getMobileTxPackets(JNIEnv* env, jobject clazz) { 1112b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return tryBoth( 1122b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor "/sys/class/net/rmnet0/statistics/tx_packets", 1132b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor "/sys/class/net/ppp0/statistics/tx_packets"); 1142b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 1152b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1162b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getMobileRxPackets(JNIEnv* env, jobject clazz) { 1172b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return tryBoth( 1182b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor "/sys/class/net/rmnet0/statistics/rx_packets", 1192b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor "/sys/class/net/ppp0/statistics/rx_packets"); 1202b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 1212b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1222b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getMobileTxBytes(JNIEnv* env, jobject clazz) { 1232b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return tryBoth( 1242b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor "/sys/class/net/rmnet0/statistics/tx_bytes", 1252b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor "/sys/class/net/ppp0/statistics/tx_bytes"); 1262b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 1272b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1282b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getMobileRxBytes(JNIEnv* env, jobject clazz) { 1292b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return tryBoth( 1302b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor "/sys/class/net/rmnet0/statistics/rx_bytes", 1312b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor "/sys/class/net/ppp0/statistics/rx_bytes"); 1322b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 1332b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 134f17b971a75577a3a0e5ab574618e0756d167f5d4Elliott Hughesstatic jlong getData(JNIEnv* env, const char* what, jstring javaInterface) { 135f17b971a75577a3a0e5ab574618e0756d167f5d4Elliott Hughes ScopedUtfChars interface(env, javaInterface); 136f17b971a75577a3a0e5ab574618e0756d167f5d4Elliott Hughes if (interface.c_str() == NULL) { 137f17b971a75577a3a0e5ab574618e0756d167f5d4Elliott Hughes return -1; 138f17b971a75577a3a0e5ab574618e0756d167f5d4Elliott Hughes } 139227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff 140f17b971a75577a3a0e5ab574618e0756d167f5d4Elliott Hughes char filename[80]; 141f17b971a75577a3a0e5ab574618e0756d167f5d4Elliott Hughes snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s", interface.c_str(), what); 142227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff return readNumber(filename); 143227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff} 144227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff 145227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriffstatic jlong getTxPackets(JNIEnv* env, jobject clazz, jstring interface) { 146227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff return getData(env, "tx_packets", interface); 147227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff} 148227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff 149227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriffstatic jlong getRxPackets(JNIEnv* env, jobject clazz, jstring interface) { 150227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff return getData(env, "rx_packets", interface); 151227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff} 152227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff 153227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriffstatic jlong getTxBytes(JNIEnv* env, jobject clazz, jstring interface) { 154227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff return getData(env, "tx_bytes", interface); 155227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff} 156227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff 157227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriffstatic jlong getRxBytes(JNIEnv* env, jobject clazz, jstring interface) { 158227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff return getData(env, "rx_bytes", interface); 159227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff} 160227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff 161227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff 1622b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// Total stats are read less often, so we're willing to put up 1632b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// with listing the directory and concatenating filenames. 1642b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1652b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getTotalTxPackets(JNIEnv* env, jobject clazz) { 1662b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return readTotal("/statistics/tx_packets"); 1672b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 1682b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1692b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getTotalRxPackets(JNIEnv* env, jobject clazz) { 1702b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return readTotal("/statistics/rx_packets"); 1712b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 1722b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1732b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getTotalTxBytes(JNIEnv* env, jobject clazz) { 1742b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return readTotal("/statistics/tx_bytes"); 1752b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 1762b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1772b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getTotalRxBytes(JNIEnv* env, jobject clazz) { 1782b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return readTotal("/statistics/rx_bytes"); 1792b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 1802b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 1812b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor// Per-UID stats require reading from a constructed filename. 1822b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 183c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidBytes(JNIEnv* env, jobject clazz, jint uid, 184c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma enum Tx_Rx tx_or_rx, enum Tcp_Udp tcp_or_udp) { 185c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma char tcp_filename[80], udp_filename[80]; 186c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma jlong tcp_bytes = -1, udp_bytes = -1, total_bytes = -1; 187c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 188c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma switch (tx_or_rx) { 189c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case TX: 190c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma sprintf(tcp_filename, "/proc/uid_stat/%d/tcp_snd", uid); 191c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma sprintf(udp_filename, "/proc/uid_stat/%d/udp_snd", uid); 192c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 193c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case RX: 194c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma sprintf(tcp_filename, "/proc/uid_stat/%d/tcp_rcv", uid); 195c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma sprintf(udp_filename, "/proc/uid_stat/%d/udp_rcv", uid); 196c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 197c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma default: 198c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return -1; 199c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma } 200c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 201c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma switch (tcp_or_udp) { 202c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case TCP: 203c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma tcp_bytes = readNumber(tcp_filename); 204c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma total_bytes = (tcp_bytes >= 0) ? tcp_bytes : -1; 205c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 206c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case UDP: 207c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma udp_bytes = readNumber(udp_filename); 208c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma total_bytes = (udp_bytes >= 0) ? udp_bytes : -1; 209c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 210c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case TCP_AND_UDP: 211c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma tcp_bytes = readNumber(tcp_filename); 212c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma total_bytes += (tcp_bytes >= 0 ? tcp_bytes : 0); 213c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 214c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma udp_bytes = readNumber(udp_filename); 215c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma total_bytes += (udp_bytes >= 0 ? udp_bytes : 0); 216c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 217c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma default: 218c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return -1; 219c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma } 220c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 221c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return total_bytes; 222c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 223c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 224c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidPkts(JNIEnv* env, jobject clazz, jint uid, 225c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma enum Tx_Rx tx_or_rx, enum Tcp_Udp tcp_or_udp) { 226c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma char tcp_filename[80], udp_filename[80]; 227c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma jlong tcp_pkts = -1, udp_pkts = -1, total_pkts = -1; 228c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 229c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma switch (tx_or_rx) { 230c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case TX: 231c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma sprintf(tcp_filename, "/proc/uid_stat/%d/tcp_snd_pkt", uid); 232c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma sprintf(udp_filename, "/proc/uid_stat/%d/udp_snd_pkt", uid); 233c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 234c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case RX: 235c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma sprintf(tcp_filename, "/proc/uid_stat/%d/tcp_rcv_pkt", uid); 236c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma sprintf(udp_filename, "/proc/uid_stat/%d/udp_rcv_pkt", uid); 237c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 238c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma default: 239c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return -1; 240c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma } 241c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 242c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma switch (tcp_or_udp) { 243c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case TCP: 244c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma tcp_pkts = readNumber(tcp_filename); 245c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma total_pkts = (tcp_pkts >= 0) ? tcp_pkts : -1; 246c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 247c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case UDP: 248c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma udp_pkts = readNumber(udp_filename); 249c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma total_pkts = (udp_pkts >= 0) ? udp_pkts : -1; 250c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 251c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma case TCP_AND_UDP: 252c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma tcp_pkts = readNumber(tcp_filename); 253c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma total_pkts += (tcp_pkts >= 0 ? tcp_pkts : 0); 254c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 255c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma udp_pkts = readNumber(udp_filename); 256c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma total_pkts += (udp_pkts >= 0 ? udp_pkts : 0); 257c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma break; 258c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma default: 259c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return -1; 260c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma } 261c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 262c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return total_pkts; 263c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 264c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 2652b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getUidRxBytes(JNIEnv* env, jobject clazz, jint uid) { 266c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidBytes(env, clazz, uid, RX, TCP_AND_UDP); 2672b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 2682b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 2692b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic jlong getUidTxBytes(JNIEnv* env, jobject clazz, jint uid) { 270c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidBytes(env, clazz, uid, TX, TCP_AND_UDP); 271c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 272c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 273c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma/* TCP Segments + UDP Packets */ 274c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidTxPackets(JNIEnv* env, jobject clazz, jint uid) { 275c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidPkts(env, clazz, uid, TX, TCP_AND_UDP); 276c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 277c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 278c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma/* TCP Segments + UDP Packets */ 279c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidRxPackets(JNIEnv* env, jobject clazz, jint uid) { 280c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidPkts(env, clazz, uid, RX, TCP_AND_UDP); 281c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 282c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 283c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidTcpTxBytes(JNIEnv* env, jobject clazz, jint uid) { 284c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidBytes(env, clazz, uid, TX, TCP); 285c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 286c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 287c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidTcpRxBytes(JNIEnv* env, jobject clazz, jint uid) { 288c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidBytes(env, clazz, uid, RX, TCP); 289c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 290c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 291c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidUdpTxBytes(JNIEnv* env, jobject clazz, jint uid) { 292c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidBytes(env, clazz, uid, TX, UDP); 293c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 294c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 295c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidUdpRxBytes(JNIEnv* env, jobject clazz, jint uid) { 296c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidBytes(env, clazz, uid, RX, UDP); 297c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 298c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 299c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidTcpTxSegments(JNIEnv* env, jobject clazz, jint uid) { 300c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidPkts(env, clazz, uid, TX, TCP); 301c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 302c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 303c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidTcpRxSegments(JNIEnv* env, jobject clazz, jint uid) { 304c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidPkts(env, clazz, uid, RX, TCP); 305c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 306c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 307c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidUdpTxPackets(JNIEnv* env, jobject clazz, jint uid) { 308c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidPkts(env, clazz, uid, TX, UDP); 309c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma} 310c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 311c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharmastatic jlong getUidUdpRxPackets(JNIEnv* env, jobject clazz, jint uid) { 312c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma return getUidPkts(env, clazz, uid, RX, UDP); 3132b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 3142b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 3152b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorstatic JNINativeMethod gMethods[] = { 3162b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getMobileTxPackets", "()J", (void*) getMobileTxPackets}, 3172b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getMobileRxPackets", "()J", (void*) getMobileRxPackets}, 3182b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getMobileTxBytes", "()J", (void*) getMobileTxBytes}, 3192b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getMobileRxBytes", "()J", (void*) getMobileRxBytes}, 320227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff {"getTxPackets", "(Ljava/lang/String;)J", (void*) getTxPackets}, 321227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff {"getRxPackets", "(Ljava/lang/String;)J", (void*) getRxPackets}, 322227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff {"getTxBytes", "(Ljava/lang/String;)J", (void*) getTxBytes}, 323227bec49157bc496f7c9e8e8f63c12728a448922Irfan Sheriff {"getRxBytes", "(Ljava/lang/String;)J", (void*) getRxBytes}, 3242b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getTotalTxPackets", "()J", (void*) getTotalTxPackets}, 3252b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getTotalRxPackets", "()J", (void*) getTotalRxPackets}, 3262b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getTotalTxBytes", "()J", (void*) getTotalTxBytes}, 3272b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getTotalRxBytes", "()J", (void*) getTotalRxBytes}, 328c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 329c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma /* Per-UID Stats */ 3302b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getUidTxBytes", "(I)J", (void*) getUidTxBytes}, 3312b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor {"getUidRxBytes", "(I)J", (void*) getUidRxBytes}, 332c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidTxPackets", "(I)J", (void*) getUidTxPackets}, 333c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidRxPackets", "(I)J", (void*) getUidRxPackets}, 334c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 335c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidTcpTxBytes", "(I)J", (void*) getUidTcpTxBytes}, 336c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidTcpRxBytes", "(I)J", (void*) getUidTcpRxBytes}, 337c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidUdpTxBytes", "(I)J", (void*) getUidUdpTxBytes}, 338c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidUdpRxBytes", "(I)J", (void*) getUidUdpRxBytes}, 339c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma 340c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidTcpTxSegments", "(I)J", (void*) getUidTcpTxSegments}, 341c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidTcpRxSegments", "(I)J", (void*) getUidTcpRxSegments}, 342c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidUdpTxPackets", "(I)J", (void*) getUidUdpTxPackets}, 343c39c1d4dee917560d174f6ba5402e4c6644edd47Ashish Sharma {"getUidUdpRxPackets", "(I)J", (void*) getUidUdpRxPackets}, 3442b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor}; 3452b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 3462b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnorint register_android_net_TrafficStats(JNIEnv* env) { 3472b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor return AndroidRuntime::registerNativeMethods(env, "android/net/TrafficStats", 3482b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor gMethods, NELEM(gMethods)); 3492b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 3502b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor 3512b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor} 352