From aa7ba31c8ee2a24eeaa116b7b6c1699d56dd5c6c Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Tue, 14 Nov 2017 17:54:17 -0800 Subject: [PATCH] Use NetworkStatsService to get stats for apps Move the native implementation of TrafficStats to NetworkStatsService and apps need to get the NetworkStatsService binder interface from system_server in order to get the network usage stats since boot. This implementation can hide the detail of retrieving network traffic information from apps and the NetworkStatsService can choose which methoed it use to get the data depending on the kernel version of the device. Bug: 30950746 Test: CtsNetTestCases -t android.net.cts.TrafficStatsTest Change-Id: I53bbefd19aa0b783b9b4b42ea4d76db3e9ec07a3 --- .../android/net/INetworkStatsService.aidl | 9 ++ core/java/android/net/TrafficStats.java | 114 ++++++++++++++---- .../server/net/NetworkStatsService.java | 26 ++++ ...android_server_net_NetworkStatsService.cpp | 22 +++- 4 files changed, 146 insertions(+), 25 deletions(-) rename core/jni/android_net_TrafficStats.cpp => services/core/jni/com_android_server_net_NetworkStatsService.cpp (80%) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 91801127fd..95e7f6031c 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -67,4 +67,13 @@ interface INetworkStatsService { /** Unregisters a callback on data usage. */ void unregisterUsageRequest(in DataUsageRequest request); + /** Get the uid stats information since boot */ + long getUidStats(int uid, int type); + + /** Get the iface stats information since boot */ + long getIfaceStats(String iface, int type); + + /** Get the total network stats information since boot */ + long getTotalStats(int type); + } diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index d701550817..196a3bc9c8 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -505,7 +505,12 @@ public class TrafficStats { public static long getMobileTcpRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { - final long stat = nativeGetIfaceStat(iface, TYPE_TCP_RX_PACKETS); + long stat = UNSUPPORTED; + try { + stat = getStatsService().getIfaceStats(iface, TYPE_TCP_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } if (stat != UNSUPPORTED) { total += stat; } @@ -517,7 +522,12 @@ public class TrafficStats { public static long getMobileTcpTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { - final long stat = nativeGetIfaceStat(iface, TYPE_TCP_TX_PACKETS); + long stat = UNSUPPORTED; + try { + stat = getStatsService().getIfaceStats(iface, TYPE_TCP_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } if (stat != UNSUPPORTED) { total += stat; } @@ -527,46 +537,78 @@ public class TrafficStats { /** {@hide} */ public static long getTxPackets(String iface) { - return nativeGetIfaceStat(iface, TYPE_TX_PACKETS); + try { + return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ public static long getRxPackets(String iface) { - return nativeGetIfaceStat(iface, TYPE_RX_PACKETS); + try { + return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ public static long getTxBytes(String iface) { - return nativeGetIfaceStat(iface, TYPE_TX_BYTES); + try { + return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ public static long getRxBytes(String iface) { - return nativeGetIfaceStat(iface, TYPE_RX_BYTES); + try { + return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ @TestApi public static long getLoopbackTxPackets() { - return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_TX_PACKETS); + try { + return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ @TestApi public static long getLoopbackRxPackets() { - return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_RX_PACKETS); + try { + return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ @TestApi public static long getLoopbackTxBytes() { - return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_TX_BYTES); + try { + return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ @TestApi public static long getLoopbackRxBytes() { - return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_RX_BYTES); + try { + return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -579,7 +621,11 @@ public class TrafficStats { * return {@link #UNSUPPORTED} on devices where statistics aren't available. */ public static long getTotalTxPackets() { - return nativeGetTotalStat(TYPE_TX_PACKETS); + try { + return getStatsService().getTotalStats(TYPE_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -592,7 +638,11 @@ public class TrafficStats { * return {@link #UNSUPPORTED} on devices where statistics aren't available. */ public static long getTotalRxPackets() { - return nativeGetTotalStat(TYPE_RX_PACKETS); + try { + return getStatsService().getTotalStats(TYPE_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -605,7 +655,11 @@ public class TrafficStats { * return {@link #UNSUPPORTED} on devices where statistics aren't available. */ public static long getTotalTxBytes() { - return nativeGetTotalStat(TYPE_TX_BYTES); + try { + return getStatsService().getTotalStats(TYPE_TX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -618,7 +672,11 @@ public class TrafficStats { * return {@link #UNSUPPORTED} on devices where statistics aren't available. */ public static long getTotalRxBytes() { - return nativeGetTotalStat(TYPE_RX_BYTES); + try { + return getStatsService().getTotalStats(TYPE_RX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -644,7 +702,11 @@ public class TrafficStats { // unsupported value. The real filtering is done at the kernel level. final int callingUid = android.os.Process.myUid(); if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - return nativeGetUidStat(uid, TYPE_TX_BYTES); + try { + return getStatsService().getUidStats(uid, TYPE_TX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } else { return UNSUPPORTED; } @@ -673,7 +735,11 @@ public class TrafficStats { // unsupported value. The real filtering is done at the kernel level. final int callingUid = android.os.Process.myUid(); if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - return nativeGetUidStat(uid, TYPE_RX_BYTES); + try { + return getStatsService().getUidStats(uid, TYPE_RX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } else { return UNSUPPORTED; } @@ -702,7 +768,11 @@ public class TrafficStats { // unsupported value. The real filtering is done at the kernel level. final int callingUid = android.os.Process.myUid(); if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - return nativeGetUidStat(uid, TYPE_TX_PACKETS); + try { + return getStatsService().getUidStats(uid, TYPE_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } else { return UNSUPPORTED; } @@ -731,7 +801,11 @@ public class TrafficStats { // unsupported value. The real filtering is done at the kernel level. final int callingUid = android.os.Process.myUid(); if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - return nativeGetUidStat(uid, TYPE_RX_PACKETS); + try { + return getStatsService().getUidStats(uid, TYPE_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } else { return UNSUPPORTED; } @@ -859,8 +933,4 @@ public class TrafficStats { 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); - private static native long nativeGetUidStat(int uid, int type); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3af5265e6f..db61ef5cd9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -873,6 +873,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + @Override + public long getUidStats(int uid, int type) { + return nativeGetUidStat(uid, type); + } + + @Override + public long getIfaceStats(String iface, int type) { + return nativeGetIfaceStat(iface, type); + } + + @Override + public long getTotalStats(int type) { + return nativeGetTotalStat(type); + } + /** * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to * reflect current {@link #mPersistThreshold} value. Always defers to @@ -1626,4 +1641,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def); } } + + private static int TYPE_RX_BYTES; + private static int TYPE_RX_PACKETS; + private static int TYPE_TX_BYTES; + private static int TYPE_TX_PACKETS; + private static int TYPE_TCP_RX_PACKETS; + private static int TYPE_TCP_TX_PACKETS; + + private static native long nativeGetTotalStat(int type); + private static native long nativeGetIfaceStat(String iface, int type); + private static native long nativeGetUidStat(int uid, int type); } diff --git a/core/jni/android_net_TrafficStats.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp similarity index 80% rename from core/jni/android_net_TrafficStats.cpp rename to services/core/jni/com_android_server_net_NetworkStatsService.cpp index d0c237da07..8de24e5565 100644 --- a/core/jni/android_net_TrafficStats.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "TrafficStats" +#define LOG_TAG "NetworkStatsNative" #include #include @@ -191,8 +191,24 @@ static const JNINativeMethod gMethods[] = { {"nativeGetUidStat", "(II)J", (void*) getUidStat}, }; -int register_android_net_TrafficStats(JNIEnv* env) { - return RegisterMethodsOrDie(env, "android/net/TrafficStats", gMethods, NELEM(gMethods)); +int register_android_server_net_NetworkStatsService(JNIEnv* env) { + jclass netStatsService = env->FindClass("com/android/server/net/NetworkStatsService"); + jfieldID rxBytesId = env->GetStaticFieldID(netStatsService, "TYPE_RX_BYTES", "I"); + jfieldID rxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_RX_PACKETS", "I"); + jfieldID txBytesId = env->GetStaticFieldID(netStatsService, "TYPE_TX_BYTES", "I"); + jfieldID txPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TX_PACKETS", "I"); + jfieldID tcpRxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_RX_PACKETS", "I"); + jfieldID tcpTxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_TX_PACKETS", "I"); + + env->SetStaticIntField(netStatsService, rxBytesId, RX_BYTES); + env->SetStaticIntField(netStatsService, rxPacketsId, RX_PACKETS); + env->SetStaticIntField(netStatsService, txBytesId, TX_BYTES); + env->SetStaticIntField(netStatsService, txPacketsId, TX_PACKETS); + env->SetStaticIntField(netStatsService, tcpRxPacketsId, TCP_RX_PACKETS); + env->SetStaticIntField(netStatsService, tcpTxPacketsId, TCP_TX_PACKETS); + + return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods, + NELEM(gMethods)); } }