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
This commit is contained in:
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "TrafficStats"
|
||||
#define LOG_TAG "NetworkStatsNative"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user