Merge changes Id26a24c8,I3b6ac97e into main am: e8184501b8

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2894583

Change-Id: I71bf4dc0c19f41946f4590a8e1698ca461c8426a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot 2024-01-04 11:01:00 +00:00 • committed by Automerger Merge Worker
commit c442143936
2 changed files with 86 additions and 73 deletions

View file

@ -34,77 +34,64 @@
using android::bpf::bpfGetUidStats;
using android::bpf::bpfGetIfaceStats;
using android::bpf::bpfGetIfIndexStats;
using android::bpf::NetworkTraceHandler;
namespace android {
// NOTE: keep these in sync with TrafficStats.java
static const uint64_t UNKNOWN = -1;
enum StatsType {
RX_BYTES = 0,
RX_PACKETS = 1,
TX_BYTES = 2,
TX_PACKETS = 3,
};
static uint64_t getStatsType(StatsValue* stats, StatsType type) {
switch (type) {
case RX_BYTES:
return stats->rxBytes;
case RX_PACKETS:
return stats->rxPackets;
case TX_BYTES:
return stats->txBytes;
case TX_PACKETS:
return stats->txPackets;
default:
return UNKNOWN;
static jobject statsValueToEntry(JNIEnv* env, StatsValue* stats) {
// Find the Java class that represents the structure
jclass gEntryClass = env->FindClass("android/net/NetworkStats$Entry");
if (gEntryClass == nullptr) {
return nullptr;
}
// Create a new instance of the Java class
jobject result = env->AllocObject(gEntryClass);
if (result == nullptr) {
return nullptr;
}
// Set the values of the structure fields in the Java object
env->SetLongField(result, env->GetFieldID(gEntryClass, "rxBytes", "J"), stats->rxBytes);
env->SetLongField(result, env->GetFieldID(gEntryClass, "txBytes", "J"), stats->txBytes);
env->SetLongField(result, env->GetFieldID(gEntryClass, "rxPackets", "J"), stats->rxPackets);
env->SetLongField(result, env->GetFieldID(gEntryClass, "txPackets", "J"), stats->txPackets);
return result;
}
static jlong nativeGetTotalStat(JNIEnv* env, jclass clazz, jint type) {
static jobject nativeGetTotalStat(JNIEnv* env, jclass clazz) {
StatsValue stats = {};
if (bpfGetIfaceStats(NULL, &stats) == 0) {
return getStatsType(&stats, (StatsType) type);
return statsValueToEntry(env, &stats);
} else {
return UNKNOWN;
return nullptr;
}
}
static jlong nativeGetIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
static jobject nativeGetIfaceStat(JNIEnv* env, jclass clazz, jstring iface) {
ScopedUtfChars iface8(env, iface);
if (iface8.c_str() == NULL) {
return UNKNOWN;
return nullptr;
}
StatsValue stats = {};
if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
return getStatsType(&stats, (StatsType) type);
return statsValueToEntry(env, &stats);
} else {
return UNKNOWN;
return nullptr;
}
}
static jlong nativeGetIfIndexStat(JNIEnv* env, jclass clazz, jint ifindex, jint type) {
StatsValue stats = {};
if (bpfGetIfIndexStats(ifindex, &stats) == 0) {
return getStatsType(&stats, (StatsType) type);
} else {
return UNKNOWN;
}
}
static jlong nativeGetUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
static jobject nativeGetUidStat(JNIEnv* env, jclass clazz, jint uid) {
StatsValue stats = {};
if (bpfGetUidStats(uid, &stats) == 0) {
return getStatsType(&stats, (StatsType) type);
return statsValueToEntry(env, &stats);
} else {
return UNKNOWN;
return nullptr;
}
}
@ -113,11 +100,26 @@ static void nativeInitNetworkTracing(JNIEnv* env, jclass clazz) {
}
static const JNINativeMethod gMethods[] = {
{"nativeGetTotalStat", "(I)J", (void*)nativeGetTotalStat},
{"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)nativeGetIfaceStat},
{"nativeGetIfIndexStat", "(II)J", (void*)nativeGetIfIndexStat},
{"nativeGetUidStat", "(II)J", (void*)nativeGetUidStat},
{"nativeInitNetworkTracing", "()V", (void*)nativeInitNetworkTracing},
{
"nativeGetTotalStat",
"()Landroid/net/NetworkStats$Entry;",
(void*)nativeGetTotalStat
},
{
"nativeGetIfaceStat",
"(Ljava/lang/String;)Landroid/net/NetworkStats$Entry;",
(void*)nativeGetIfaceStat
},
{
"nativeGetUidStat",
"(I)Landroid/net/NetworkStats$Entry;",
(void*)nativeGetUidStat
},
{
"nativeInitNetworkTracing",
"()V",
(void*)nativeInitNetworkTracing
},
};
int register_android_server_net_NetworkStatsService(JNIEnv* env) {

View file

@ -1981,36 +1981,56 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) {
return UNSUPPORTED;
}
return nativeGetUidStat(uid, type);
return getEntryValueForType(nativeGetUidStat(uid), type);
}
@Override
public long getIfaceStats(@NonNull String iface, int type) {
Objects.requireNonNull(iface);
long nativeIfaceStats = nativeGetIfaceStat(iface, type);
if (nativeIfaceStats == -1) {
return nativeIfaceStats;
final NetworkStats.Entry entry = nativeGetIfaceStat(iface);
final long value = getEntryValueForType(entry, type);
if (value == UNSUPPORTED) {
return UNSUPPORTED;
} else {
// When tethering offload is in use, nativeIfaceStats does not contain usage from
// offload, add it back here. Note that the included statistics might be stale
// since polling newest stats from hardware might impact system health and not
// suitable for TrafficStats API use cases.
return nativeIfaceStats + getProviderIfaceStats(iface, type);
entry.add(getProviderIfaceStats(iface));
return getEntryValueForType(entry, type);
}
}
private long getEntryValueForType(@Nullable NetworkStats.Entry entry, int type) {
if (entry == null) return UNSUPPORTED;
switch (type) {
case TrafficStats.TYPE_RX_BYTES:
return entry.rxBytes;
case TrafficStats.TYPE_TX_BYTES:
return entry.txBytes;
case TrafficStats.TYPE_RX_PACKETS:
return entry.rxPackets;
case TrafficStats.TYPE_TX_PACKETS:
return entry.txPackets;
default:
return UNSUPPORTED;
}
}
@Override
public long getTotalStats(int type) {
long nativeTotalStats = nativeGetTotalStat(type);
if (nativeTotalStats == -1) {
return nativeTotalStats;
final NetworkStats.Entry entry = nativeGetTotalStat();
final long value = getEntryValueForType(entry, type);
if (value == UNSUPPORTED) {
return UNSUPPORTED;
} else {
// Refer to comment in getIfaceStats
return nativeTotalStats + getProviderIfaceStats(IFACE_ALL, type);
entry.add(getProviderIfaceStats(IFACE_ALL));
return getEntryValueForType(entry, type);
}
}
private long getProviderIfaceStats(@Nullable String iface, int type) {
private NetworkStats.Entry getProviderIfaceStats(@Nullable String iface) {
final NetworkStats providerSnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
final HashSet<String> limitIfaces;
if (iface == IFACE_ALL) {
@ -2019,19 +2039,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
limitIfaces = new HashSet<>();
limitIfaces.add(iface);
}
final NetworkStats.Entry entry = providerSnapshot.getTotal(null, limitIfaces);
switch (type) {
case TrafficStats.TYPE_RX_BYTES:
return entry.rxBytes;
case TrafficStats.TYPE_RX_PACKETS:
return entry.rxPackets;
case TrafficStats.TYPE_TX_BYTES:
return entry.txBytes;
case TrafficStats.TYPE_TX_PACKETS:
return entry.txPackets;
default:
return 0;
}
return providerSnapshot.getTotal(null, limitIfaces);
}
/**
@ -3398,10 +3406,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
private static native long nativeGetTotalStat(int type);
private static native long nativeGetIfaceStat(String iface, int type);
private static native long nativeGetIfIndexStat(int ifindex, int type);
private static native long nativeGetUidStat(int uid, int type);
// TODO: Read stats by using BpfNetMapsReader.
@Nullable
private static native NetworkStats.Entry nativeGetTotalStat();
@Nullable
private static native NetworkStats.Entry nativeGetIfaceStat(String iface);
@Nullable
private static native NetworkStats.Entry nativeGetUidStat(int uid);
/** Initializes and registers the Perfetto Network Trace data source */
public static native void nativeInitNetworkTracing();