Merge changes from topic "bpfStats"
* changes: Use /proc/net/dev to get stats summary Add bpf support for NetworkStatsFactory Add BPF support for NetworkStatsService
This commit is contained in:
@@ -31,13 +31,17 @@ import com.android.internal.annotations.GuardedBy;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
import com.android.internal.util.ProcFileReader;
|
import com.android.internal.util.ProcFileReader;
|
||||||
|
import com.google.android.collect.Lists;
|
||||||
|
|
||||||
import libcore.io.IoUtils;
|
import libcore.io.IoUtils;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ProtocolException;
|
import java.net.ProtocolException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,6 +59,8 @@ public class NetworkStatsFactory {
|
|||||||
// Used for correct stats accounting on clatd interfaces.
|
// Used for correct stats accounting on clatd interfaces.
|
||||||
private static final int IPV4V6_HEADER_DELTA = 20;
|
private static final int IPV4V6_HEADER_DELTA = 20;
|
||||||
|
|
||||||
|
/** Path to {@code /proc/net/dev}. */
|
||||||
|
private final File mStatsIfaceDev;
|
||||||
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
|
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
|
||||||
private final File mStatsXtIfaceAll;
|
private final File mStatsXtIfaceAll;
|
||||||
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
|
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
|
||||||
@@ -62,6 +68,8 @@ public class NetworkStatsFactory {
|
|||||||
/** Path to {@code /proc/net/xt_qtaguid/stats}. */
|
/** Path to {@code /proc/net/xt_qtaguid/stats}. */
|
||||||
private final File mStatsXtUid;
|
private final File mStatsXtUid;
|
||||||
|
|
||||||
|
private boolean mUseBpfStats;
|
||||||
|
|
||||||
// TODO: to improve testability and avoid global state, do not use a static variable.
|
// TODO: to improve testability and avoid global state, do not use a static variable.
|
||||||
@GuardedBy("sStackedIfaces")
|
@GuardedBy("sStackedIfaces")
|
||||||
private static final ArrayMap<String, String> sStackedIfaces = new ArrayMap<>();
|
private static final ArrayMap<String, String> sStackedIfaces = new ArrayMap<>();
|
||||||
@@ -77,14 +85,54 @@ public class NetworkStatsFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public NetworkStatsFactory() {
|
public NetworkStatsFactory() {
|
||||||
this(new File("/proc/"));
|
this(new File("/proc/"), new File("/sys/fs/bpf/traffic_uid_stats_map").exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public NetworkStatsFactory(File procRoot) {
|
public NetworkStatsFactory(File procRoot, boolean useBpfStats) {
|
||||||
|
mStatsIfaceDev = new File(procRoot, "net/dev");
|
||||||
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
|
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
|
||||||
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
|
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
|
||||||
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
|
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
|
||||||
|
mUseBpfStats = useBpfStats;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public NetworkStats readNetworkStatsIfaceDev() throws IOException {
|
||||||
|
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
||||||
|
|
||||||
|
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
|
||||||
|
final NetworkStats.Entry entry = new NetworkStats.Entry();
|
||||||
|
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try {
|
||||||
|
reader = new BufferedReader(new FileReader(mStatsIfaceDev));
|
||||||
|
|
||||||
|
// skip first two header lines
|
||||||
|
reader.readLine();
|
||||||
|
reader.readLine();
|
||||||
|
|
||||||
|
// parse remaining lines
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
String[] values = line.trim().split("\\:?\\s+");
|
||||||
|
entry.iface = values[0];
|
||||||
|
entry.uid = UID_ALL;
|
||||||
|
entry.set = SET_ALL;
|
||||||
|
entry.tag = TAG_NONE;
|
||||||
|
entry.rxBytes = Long.parseLong(values[1]);
|
||||||
|
entry.rxPackets = Long.parseLong(values[2]);
|
||||||
|
entry.txBytes = Long.parseLong(values[9]);
|
||||||
|
entry.txPackets = Long.parseLong(values[10]);
|
||||||
|
stats.addValues(entry);
|
||||||
|
}
|
||||||
|
} catch (NullPointerException|NumberFormatException e) {
|
||||||
|
throw new ProtocolException("problem parsing stats", e);
|
||||||
|
} finally {
|
||||||
|
IoUtils.closeQuietly(reader);
|
||||||
|
StrictMode.setThreadPolicy(savedPolicy);
|
||||||
|
}
|
||||||
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,6 +144,11 @@ public class NetworkStatsFactory {
|
|||||||
* @throws IllegalStateException when problem parsing stats.
|
* @throws IllegalStateException when problem parsing stats.
|
||||||
*/
|
*/
|
||||||
public NetworkStats readNetworkStatsSummaryDev() throws IOException {
|
public NetworkStats readNetworkStatsSummaryDev() throws IOException {
|
||||||
|
|
||||||
|
// Return the stats get from /proc/net/dev if switched to bpf module.
|
||||||
|
if (mUseBpfStats)
|
||||||
|
return readNetworkStatsIfaceDev();
|
||||||
|
|
||||||
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
||||||
|
|
||||||
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
|
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
|
||||||
@@ -147,6 +200,11 @@ public class NetworkStatsFactory {
|
|||||||
* @throws IllegalStateException when problem parsing stats.
|
* @throws IllegalStateException when problem parsing stats.
|
||||||
*/
|
*/
|
||||||
public NetworkStats readNetworkStatsSummaryXt() throws IOException {
|
public NetworkStats readNetworkStatsSummaryXt() throws IOException {
|
||||||
|
|
||||||
|
// Return the stats get from /proc/net/dev if qtaguid module is replaced.
|
||||||
|
if (mUseBpfStats)
|
||||||
|
return readNetworkStatsIfaceDev();
|
||||||
|
|
||||||
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
||||||
|
|
||||||
// return null when kernel doesn't support
|
// return null when kernel doesn't support
|
||||||
@@ -252,7 +310,7 @@ public class NetworkStatsFactory {
|
|||||||
stats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
|
stats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
|
||||||
}
|
}
|
||||||
if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid,
|
if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid,
|
||||||
limitIfaces, limitTag) != 0) {
|
limitIfaces, limitTag, mUseBpfStats) != 0) {
|
||||||
throw new IOException("Failed to parse network stats");
|
throw new IOException("Failed to parse network stats");
|
||||||
}
|
}
|
||||||
if (SANITY_CHECK_NATIVE) {
|
if (SANITY_CHECK_NATIVE) {
|
||||||
@@ -346,6 +404,6 @@ public class NetworkStatsFactory {
|
|||||||
* are expected to monotonically increase since device boot.
|
* are expected to monotonically increase since device boot.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static native int nativeReadNetworkStatsDetail(
|
public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path,
|
||||||
NetworkStats stats, String path, int limitUid, String[] limitIfaces, int limitTag);
|
int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,14 @@
|
|||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <utils/misc.h>
|
#include <utils/misc.h>
|
||||||
#include <utils/Vector.h>
|
|
||||||
|
#include "android-base/unique_fd.h"
|
||||||
|
#include "bpf/BpfNetworkStats.h"
|
||||||
|
#include "bpf/BpfUtils.h"
|
||||||
|
|
||||||
|
using android::bpf::hasBpfSupport;
|
||||||
|
using android::bpf::parseBpfNetworkStatsDetail;
|
||||||
|
using android::bpf::stats_line;
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@@ -53,17 +60,6 @@ static struct {
|
|||||||
jfieldID operations;
|
jfieldID operations;
|
||||||
} gNetworkStatsClassInfo;
|
} gNetworkStatsClassInfo;
|
||||||
|
|
||||||
struct stats_line {
|
|
||||||
char iface[32];
|
|
||||||
int32_t uid;
|
|
||||||
int32_t set;
|
|
||||||
int32_t tag;
|
|
||||||
int64_t rxBytes;
|
|
||||||
int64_t rxPackets;
|
|
||||||
int64_t txBytes;
|
|
||||||
int64_t txPackets;
|
|
||||||
};
|
|
||||||
|
|
||||||
static jobjectArray get_string_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
|
static jobjectArray get_string_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
|
||||||
{
|
{
|
||||||
if (!grow) {
|
if (!grow) {
|
||||||
@@ -97,33 +93,14 @@ static jlongArray get_long_array(JNIEnv* env, jobject obj, jfieldID field, int s
|
|||||||
return env->NewLongArray(size);
|
return env->NewLongArray(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
|
static int legacyReadNetworkStatsDetail(std::vector<stats_line>* lines,
|
||||||
jstring path, jint limitUid, jobjectArray limitIfacesObj, jint limitTag) {
|
const std::vector<std::string>& limitIfaces,
|
||||||
ScopedUtfChars path8(env, path);
|
int limitTag, int limitUid, const char* path) {
|
||||||
if (path8.c_str() == NULL) {
|
FILE* fp = fopen(path, "r");
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fp = fopen(path8.c_str(), "r");
|
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<String8> limitIfaces;
|
|
||||||
if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
|
|
||||||
int num = env->GetArrayLength(limitIfacesObj);
|
|
||||||
limitIfaces.setCapacity(num);
|
|
||||||
for (int i=0; i<num; i++) {
|
|
||||||
jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
|
|
||||||
ScopedUtfChars string8(env, string);
|
|
||||||
if (string8.c_str() != NULL) {
|
|
||||||
limitIfaces.add(String8(string8.c_str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<stats_line> lines;
|
|
||||||
|
|
||||||
int lastIdx = 1;
|
int lastIdx = 1;
|
||||||
int idx;
|
int idx;
|
||||||
char buffer[384];
|
char buffer[384];
|
||||||
@@ -215,7 +192,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
|
|||||||
//ALOGI("skipping due to uid: %s", buffer);
|
//ALOGI("skipping due to uid: %s", buffer);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
lines.push_back(s);
|
lines->push_back(s);
|
||||||
} else {
|
} else {
|
||||||
//ALOGI("skipping due to bad remaining fields: %s", pos);
|
//ALOGI("skipping due to bad remaining fields: %s", pos);
|
||||||
}
|
}
|
||||||
@@ -225,8 +202,42 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
|
|||||||
ALOGE("Failed to close netstats file");
|
ALOGE("Failed to close netstats file");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
|
||||||
|
jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
|
||||||
|
jboolean useBpfStats) {
|
||||||
|
ScopedUtfChars path8(env, path);
|
||||||
|
if (path8.c_str() == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> limitIfaces;
|
||||||
|
if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
|
||||||
|
int num = env->GetArrayLength(limitIfacesObj);
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
|
||||||
|
ScopedUtfChars string8(env, string);
|
||||||
|
if (string8.c_str() != NULL) {
|
||||||
|
limitIfaces.push_back(std::string(string8.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<stats_line> lines;
|
||||||
|
|
||||||
|
|
||||||
|
if (useBpfStats) {
|
||||||
|
if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
|
||||||
|
limitUid, path8.c_str()) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int size = lines.size();
|
int size = lines.size();
|
||||||
|
|
||||||
bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
|
bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
|
||||||
|
|
||||||
ScopedLocalRef<jobjectArray> iface(env, get_string_array(env, stats,
|
ScopedLocalRef<jobjectArray> iface(env, get_string_array(env, stats,
|
||||||
@@ -303,7 +314,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
|
|||||||
|
|
||||||
static const JNINativeMethod gMethods[] = {
|
static const JNINativeMethod gMethods[] = {
|
||||||
{ "nativeReadNetworkStatsDetail",
|
{ "nativeReadNetworkStatsDetail",
|
||||||
"(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;I)I",
|
"(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",
|
||||||
(void*) readNetworkStatsDetail }
|
(void*) readNetworkStatsDetail }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -887,17 +887,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getUidStats(int uid, int type) {
|
public long getUidStats(int uid, int type) {
|
||||||
return nativeGetUidStat(uid, type);
|
return nativeGetUidStat(uid, type, checkBpfStatsEnable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getIfaceStats(String iface, int type) {
|
public long getIfaceStats(String iface, int type) {
|
||||||
return nativeGetIfaceStat(iface, type);
|
return nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTotalStats(int type) {
|
public long getTotalStats(int type) {
|
||||||
return nativeGetTotalStat(type);
|
return nativeGetTotalStat(type, checkBpfStatsEnable());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkBpfStatsEnable() {
|
||||||
|
return new File("/sys/fs/bpf/traffic_uid_stats_map").exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1668,7 +1672,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
private static int TYPE_TCP_RX_PACKETS;
|
private static int TYPE_TCP_RX_PACKETS;
|
||||||
private static int TYPE_TCP_TX_PACKETS;
|
private static int TYPE_TCP_TX_PACKETS;
|
||||||
|
|
||||||
private static native long nativeGetTotalStat(int type);
|
private static native long nativeGetTotalStat(int type, boolean useBpfStats);
|
||||||
private static native long nativeGetIfaceStat(String iface, int type);
|
private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats);
|
||||||
private static native long nativeGetUidStat(int uid, int type);
|
private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,15 @@
|
|||||||
#include <utils/misc.h>
|
#include <utils/misc.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
|
|
||||||
|
#include "android-base/unique_fd.h"
|
||||||
|
#include "bpf/BpfNetworkStats.h"
|
||||||
|
#include "bpf/BpfUtils.h"
|
||||||
|
|
||||||
|
using android::bpf::Stats;
|
||||||
|
using android::bpf::hasBpfSupport;
|
||||||
|
using android::bpf::bpfGetUidStats;
|
||||||
|
using android::bpf::bpfGetIfaceStats;
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
static const char* QTAGUID_IFACE_STATS = "/proc/net/xt_qtaguid/iface_stat_fmt";
|
static const char* QTAGUID_IFACE_STATS = "/proc/net/xt_qtaguid/iface_stat_fmt";
|
||||||
@@ -46,15 +55,6 @@ enum StatsType {
|
|||||||
TCP_TX_PACKETS = 5
|
TCP_TX_PACKETS = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Stats {
|
|
||||||
uint64_t rxBytes;
|
|
||||||
uint64_t rxPackets;
|
|
||||||
uint64_t txBytes;
|
|
||||||
uint64_t txPackets;
|
|
||||||
uint64_t tcpRxPackets;
|
|
||||||
uint64_t tcpTxPackets;
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint64_t getStatsType(struct Stats* stats, StatsType type) {
|
static uint64_t getStatsType(struct Stats* stats, StatsType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case RX_BYTES:
|
case RX_BYTES:
|
||||||
@@ -150,9 +150,18 @@ static int parseUidStats(const uint32_t uid, struct Stats* stats) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
|
static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) {
|
||||||
struct Stats stats;
|
struct Stats stats;
|
||||||
memset(&stats, 0, sizeof(Stats));
|
memset(&stats, 0, sizeof(Stats));
|
||||||
|
|
||||||
|
if (useBpfStats) {
|
||||||
|
if (bpfGetIfaceStats(NULL, &stats) == 0) {
|
||||||
|
return getStatsType(&stats, (StatsType) type);
|
||||||
|
} else {
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (parseIfaceStats(NULL, &stats) == 0) {
|
if (parseIfaceStats(NULL, &stats) == 0) {
|
||||||
return getStatsType(&stats, (StatsType) type);
|
return getStatsType(&stats, (StatsType) type);
|
||||||
} else {
|
} else {
|
||||||
@@ -160,7 +169,8 @@ static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
|
static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type,
|
||||||
|
jboolean useBpfStats) {
|
||||||
ScopedUtfChars iface8(env, iface);
|
ScopedUtfChars iface8(env, iface);
|
||||||
if (iface8.c_str() == NULL) {
|
if (iface8.c_str() == NULL) {
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
@@ -168,6 +178,15 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
|
|||||||
|
|
||||||
struct Stats stats;
|
struct Stats stats;
|
||||||
memset(&stats, 0, sizeof(Stats));
|
memset(&stats, 0, sizeof(Stats));
|
||||||
|
|
||||||
|
if (useBpfStats) {
|
||||||
|
if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
|
||||||
|
return getStatsType(&stats, (StatsType) type);
|
||||||
|
} else {
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (parseIfaceStats(iface8.c_str(), &stats) == 0) {
|
if (parseIfaceStats(iface8.c_str(), &stats) == 0) {
|
||||||
return getStatsType(&stats, (StatsType) type);
|
return getStatsType(&stats, (StatsType) type);
|
||||||
} else {
|
} else {
|
||||||
@@ -175,9 +194,18 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
|
static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) {
|
||||||
struct Stats stats;
|
struct Stats stats;
|
||||||
memset(&stats, 0, sizeof(Stats));
|
memset(&stats, 0, sizeof(Stats));
|
||||||
|
|
||||||
|
if (useBpfStats) {
|
||||||
|
if (bpfGetUidStats(uid, &stats) == 0) {
|
||||||
|
return getStatsType(&stats, (StatsType) type);
|
||||||
|
} else {
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (parseUidStats(uid, &stats) == 0) {
|
if (parseUidStats(uid, &stats) == 0) {
|
||||||
return getStatsType(&stats, (StatsType) type);
|
return getStatsType(&stats, (StatsType) type);
|
||||||
} else {
|
} else {
|
||||||
@@ -186,9 +214,9 @@ static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const JNINativeMethod gMethods[] = {
|
static const JNINativeMethod gMethods[] = {
|
||||||
{"nativeGetTotalStat", "(I)J", (void*) getTotalStat},
|
{"nativeGetTotalStat", "(IZ)J", (void*) getTotalStat},
|
||||||
{"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*) getIfaceStat},
|
{"nativeGetIfaceStat", "(Ljava/lang/String;IZ)J", (void*) getIfaceStat},
|
||||||
{"nativeGetUidStat", "(II)J", (void*) getUidStat},
|
{"nativeGetUidStat", "(IIZ)J", (void*) getUidStat},
|
||||||
};
|
};
|
||||||
|
|
||||||
int register_android_server_net_NetworkStatsService(JNIEnv* env) {
|
int register_android_server_net_NetworkStatsService(JNIEnv* env) {
|
||||||
|
|||||||
Reference in New Issue
Block a user