Loading core/java/android/net/INetworkStatsService.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -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); Loading core/java/android/net/NetworkTemplate.java +38 −8 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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"); } Loading Loading @@ -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; } Loading @@ -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: Loading @@ -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"; } Loading core/java/android/net/TrafficStats.java +86 −20 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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); } Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading Loading @@ -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. Loading Loading @@ -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); } core/jni/android_net_TrafficStats.cpp +79 −119 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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]; Loading @@ -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. Loading Loading @@ -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}, Loading services/java/com/android/server/net/NetworkStatsService.java +19 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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) { Loading Loading @@ -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); } } } } } Loading Loading @@ -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); Loading Loading @@ -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(); Loading Loading
core/java/android/net/INetworkStatsService.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
core/java/android/net/NetworkTemplate.java +38 −8 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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"); } Loading Loading @@ -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; } Loading @@ -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: Loading @@ -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"; } Loading
core/java/android/net/TrafficStats.java +86 −20 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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); } Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading @@ -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. Loading Loading @@ -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. Loading Loading @@ -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); }
core/jni/android_net_TrafficStats.cpp +79 −119 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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]; Loading @@ -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. Loading Loading @@ -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}, Loading
services/java/com/android/server/net/NetworkStatsService.java +19 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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) { Loading Loading @@ -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); } } } } } Loading Loading @@ -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); Loading Loading @@ -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(); Loading